P1343 地震逃生
题目描述
汶川地震发生时,四川**中学正在上课,一看地震发生,老师们立刻带领x名学生逃跑,整个学校可以抽象地看成一个有向图,图中有n个点,m条边。1号点为教室,n号点为安全地带,每条边都只能容纳一定量的学生,超过楼就要倒塌,由于人数太多,校长决定让同学们分成几批逃生,只有第一批学生全部逃生完毕后,第二批学生才能从1号点出发逃生,现在请你帮校长算算,每批最多能运出多少个学生,x名学生分几批才能运完。
输入输出格式
输入格式:
第一行3个整数n,m,x(x<2^31,n<=200,m<=2000);以下m行,每行三个整数a,b,c(a1,a<>b,0描述一条边,分别代表从a点到b点有一条边,且可容纳c名学生。
输出格式:
两个整数,分别表示每批最多能运出多少个学生,x名学生分几批才能运完。如果无法到达目的地(n号点)则输出“Orz Ni Jinan Saint Cow!”
输入输出样例
输入样例#1:
6 7 7 1 2 1 1 4 2 2 3 1 4 5 1 4 3 1 3 6 2 5 6 1
输出样例#1:
3 3
说明
【注释】
比如有图
1 2 100
2 3 1
100个学生先冲到2号点,然后1个1个慢慢沿2-3边走过去
18神牛规定这样是不可以的……
也就是说,每批学生必须同时从起点出发,并且同时到达终点
来一发Dinic。
这题比较少,我们想一下,如果要输送学生,我们只要找出每次可以通过的最大的学生数量就好。
然后用一点贪心的原理,每次都去用最大的输送方案输送学生(废话。。)
只要最大流不为0就一定能输送完成
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #include<algorithm> 7 #define lli long long int 8 using namespace std; 9 const int MAXN=300001; 10 const int maxn=0x7fffff; 11 void read(int &n) 12 { 13 char c='+';int x=0;bool flag=0; 14 while(c<'0'||c>'9') 15 {c=getchar();if(c=='-')flag=1;} 16 while(c>='0'&&c<='9') 17 {x=(x<<1)+(x<<3)+c-48;c=getchar();} 18 flag==1?n=-x:n=x; 19 } 20 struct node 21 { 22 int u,v,flow,cap,nxt; 23 }edge[MAXN]; 24 int head[MAXN]; 25 int num=0; 26 int n,m,S,T,x; 27 int dis[MAXN]; 28 int vis[MAXN]; 29 int cur[MAXN]; 30 void add_edge(int x,int y,int z) 31 { 32 edge[num].u=x; 33 edge[num].v=y; 34 edge[num].cap=z; 35 edge[num].flow=0; 36 edge[num].nxt=head[x]; 37 head[x]=num++; 38 } 39 bool bfs(int bg,int ed) 40 { 41 memset(dis,-1,sizeof(dis)); 42 queue<int>q; 43 q.push(bg); 44 dis[bg]=0; 45 while(!q.empty()) 46 { 47 int p=q.front(); 48 q.pop(); 49 for(int i=head[p];i!=-1;i=edge[i].nxt) 50 { 51 if(dis[edge[i].v]==-1&&edge[i].cap>edge[i].flow) 52 { 53 vis[edge[i].v]=1; 54 dis[edge[i].v]=dis[edge[i].u]+1; 55 q.push(edge[i].v); 56 } 57 } 58 } 59 if(dis[ed]==-1) 60 return 0; 61 else return 1; 62 } 63 int dfs(int now,int a)// a:所有弧的最小残量 64 { 65 if(now==T||a<=0) 66 return a; 67 68 int flow=0,f; 69 for(int i=head[now];i!=-1;i=edge[i].nxt) 70 { 71 if(dis[now]+1==dis[edge[i].v]&&edge[i].cap-edge[i].flow>0) 72 { 73 f=dfs(edge[i].v,min(a,edge[i].cap-edge[i].flow)); 74 edge[i].flow+=f; 75 edge[i^1].flow-=f; 76 flow+=f; 77 a-=f; 78 if(a<=0)break; 79 } 80 } 81 return flow; 82 } 83 void Dinic(int S,int T) 84 { 85 int ansflow=0; 86 int cs=0; 87 int maxflow=0; 88 for(int i=1;i<=n;i++) 89 cur[i]=head[i]; 90 while(bfs(S,T)) 91 { 92 int p=dfs(S,maxn); 93 cs++; 94 ansflow+=p; 95 maxflow=max(maxflow,p); 96 }// 求出层级 97 if(ansflow==0) 98 printf("Orz Ni Jinan Saint Cow!"); 99 else 100 printf("%d %d",ansflow,(x%ansflow)==0?(x/ansflow):(x/ansflow+1)); 101 102 //printf("%d",ansflow); 103 104 } 105 int main() 106 { 107 scanf("%d%d%d",&n,&m,&x); 108 //read(n);read(m);read(x); 109 // swap(n,m); 110 S=1;T=n; 111 // read(S);read(T); 112 for(int i=1;i<=n;i++) 113 head[i]=-1; 114 for(int i=1;i<=m;i++) 115 { 116 int x,y,z; 117 //read(x);read(y);read(z); 118 scanf("%d%d%d",&x,&y,&z); 119 add_edge(x,y,z); 120 add_edge(y,x,0); 121 } 122 Dinic(S,T); 123 return 0; 124 }
作者:自为风月马前卒
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。