码迷,mamicode.com
首页 > 其他好文 > 详细

Lunch Time

时间:2014-08-19 12:27:24      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   for   ar   

hdu4807:http://acm.hdu.edu.cn/showproblem.php?pid=4807

题意:给你n个点(0--n-1),点之间是有向边,0号点有k个人,现在0号点的k个人要到n-1号点。每条边有一个容量,就是单位时间内最多允许c个人通过,通过一条边需要一个单位时间,现在问你最后一个到达n-1号点最短的时间是多少。

题解:这题用到网络流。怎么用呢?首先建图,边的容量自然是原来的容量,费用肯定为1.接着,我们可以想。先选一条路径的话,我们肯定选择一条费用最少的,这里就是距离最短的一条,因为,如果选择其他的一条,当那一条到达时,这一条已经到达,不会影响最后一个人的到达,只会贡献人数的减少。所以肯定选择费用最少的一条。然后,直选一条行不?答案是不一定的,因为这一条仅仅是费用最少,但是容量不一定是最大的。当第一个人到达的时候,接下来每一秒都会有y个人到达,y是流量。所以我们遍历下一条,选择下一条的时候,前一条肯要选,因为前一条不会影响这一条,并且会减少人数,提高运输量。所以,我们要遍历所有可行路径。s[i]表示到第i条时候第一次可以运输的总人数,则可以退出递推关系系s[i]=y[i] +(d[i]-d[i-1])*sum[i-1],y[i]表示第i条可行路径的流量,sum[i-1]表示前i-1条额流量和,d[i]表示第i条路径的费用。然后求费用流的时候更新就可以了。但是还要注意k==0时候要特判。

bubuko.com,布布扣
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cmath>
  7 #define inf 100000000
  8 using namespace std;
  9 const int E=1000000;
 10 const int N=10002;
 11 struct Node{
 12     int v, cap, cost, next;    //  re记录逆边的下标。
 13 }edge[E];
 14 int n, m;
 15 long long ans,people;
 16 int k, head[N];
 17 int que[N], pre[N], dis[N];
 18 bool vis[N];
 19 void init(){//初始化
 20    k=ans=0;
 21    memset(head,-1,sizeof(head));
 22 }
 23 void addEdge(int u, int v, int ca, int co){
 24     edge[k].v = v;
 25     edge[k].cap = ca;
 26     edge[k].cost = co;
 27     edge[k].next = head[u];
 28     head[u] = k ++;
 29     edge[k].v = u;
 30     edge[k].cap = 0;
 31     edge[k].cost = -co;
 32     edge[k].next = head[v];
 33     head[v] = k ++;
 34 }
 35 bool spfa(){                  //  源点为0,汇点为n。
 36     int i;
 37     for(i = 1; i <= n; i ++){
 38         dis[i] = inf;
 39         vis[i] = false;
 40     }
 41     queue<int>Q;
 42     Q.push(1);
 43     dis[1]=0;
 44     vis[1] = true;
 45     while(!Q.empty()){       //  这里最好用队列,有广搜的意思,堆栈像深搜。
 46         int u = Q.front();
 47         Q.pop();
 48         for(i = head[u]; i != -1; i = edge[i].next){
 49             int v = edge[i].v;
 50             if(edge[i].cap && dis[v] > dis[u] + edge[i].cost){
 51                 dis[v] = dis[u] + edge[i].cost;
 52                 pre[v] = i;
 53                 if(!vis[v]){
 54                     vis[v] = true;
 55                    Q.push(v);
 56                 }
 57             }
 58         }
 59         vis[u] = false;
 60     }
 61     if(dis[n] == inf) return false;
 62     return true;
 63 }
 64 int  end(){
 65     int u, p, sum = inf;
 66     for(u = n; u != 1; u = edge[p^1].v){//0是超级源点
 67         p = pre[u];
 68         sum = min(sum, edge[p].cap);
 69     }
 70     for(u = n; u != 1; u = edge[p^1].v){
 71         p = pre[u];
 72         edge[p].cap -= sum;
 73         edge[p^1].cap += sum;
 74     }
 75     return sum;
 76 }
 77 int main(){
 78     int t1,t2,t3;
 79    while(~scanf("%d%d%d",&n,&m,&people)&&n>0){
 80         init();//初始化
 81        for(int i=1;i<=m;i++){
 82         scanf("%d%d%d",&t1,&t2,&t3);
 83           t1++;t2++;
 84           addEdge(t1,t2,t3,1);//无向图要建边两次
 85        }
 86        long long s=people,now=0,sum=0;
 87        ans=inf;
 88        while(spfa()){
 89           int y=end();
 90            s-=((long long)dis[n]-now)*sum+y;
 91            if(s<0)s=0;
 92            sum+=y;now=dis[n];
 93            long long temp=(long long)now+(long long)ceil(s*1.0/sum);
 94            if(temp<ans)ans=temp;
 95        }
 96        if(people==0)ans=0;
 97        if(ans==inf)printf("No solution\n");
 98        else
 99        printf("%I64d\n",ans);
100    }
101 }
View Code

 

Lunch Time,布布扣,bubuko.com

Lunch Time

标签:style   blog   http   color   os   io   for   ar   

原文地址:http://www.cnblogs.com/chujian123/p/3921563.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!