POJ-2455 Secret Milking Machine 二分+最大流
题目链接:http://poj.org/problem?id=2455
题意有点绕,简而言之就是要你找出T条每条边都边不重复的路径,使得的这T条路径中的每段路径的最大值最小,求出这个最大值。首先找出T条边不重复的路径,可以想到用增光路来搞,把每条边的权值赋值为1,那整个网络的最大流就是边不重复的路径的数目了,因为每条边的流量为1,最多只能在一条增广路上,所以最终由多少个可行流就有多少条边不重复的路径,就是最大流了。那么这样就可以比较快的求出来。然后发现,给图的边加个限制,即权值小于等于limit的为可行边,那么T和limit是个线性关系,就可以二分来搞了。然后要注意这个题目的数据有平行边,我因为开始没有注意,WA到死啊!血的教训!
1 //STATUS:G++_AC_282MS_2432KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 #include<map> 13 using namespace std; 14 #define LL long long 15 #define Max(a,b) ((a)>(b)?(a):(b)) 16 #define Min(a,b) ((a)<(b)?(a):(b)) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 const int MAX=210,INF=0x3f3f3f3f; 21 22 struct Edge{ 23 int u,v,c; 24 }e[MAX*MAX*2]; 25 26 struct List{ 27 int a,b,len; 28 }l[MAX*MAX]; 29 30 int d[MAX],cur[MAX]; 31 int first[MAX],next[MAX*MAX*2]; 32 int n,m,k,maxlen,minlen,mm; 33 34 void addedge(int u,int v) 35 { 36 e[mm].u=u;e[mm].v=v; 37 e[mm].c=1; 38 next[mm]=first[u],first[u]=mm++; 39 e[mm].u=v;e[mm].v=u; 40 e[mm].c=1; 41 next[mm]=first[v],first[v]=mm++; 42 } 43 44 int bfs(int s,int t) 45 { 46 int x,i; 47 queue<int> q; 48 mem(d,0); 49 d[s]=1; 50 q.push(s); 51 while(!q.empty()){ 52 x=q.front();q.pop(); 53 for(i=first[x];i!=-1;i=next[i]){ 54 if(e[i].c>0 && !d[e[i].v]){ 55 d[e[i].v]=d[x]+1; 56 q.push(e[i].v); 57 } 58 } 59 } 60 return d[t]; 61 } 62 63 int dfs(int x,int a) 64 { 65 if(x==n || a==0)return a; 66 int t,f,flow=0; 67 for(int& i=cur[x];i!=-1;i=next[i]){ 68 if(d[x]+1==d[e[i].v] && (f=dfs(e[i].v,Min(a,e[i].c)))>0){ 69 e[i].c-=f; 70 e[i^1].c+=f; 71 flow+=f; 72 a-=f; 73 if(!a)break; 74 } 75 } 76 return flow; 77 } 78 79 int dinic(int s,int t,int limit) 80 { 81 int i,ret=0; 82 while(bfs(s,t)){ 83 for(i=1;i<=n;i++)cur[i]=first[i]; 84 ret+=dfs(s,INF); 85 } 86 return ret; 87 } 88 89 int binary() 90 { 91 int i,t,low=minlen,mid,high=maxlen; 92 while(low<high){ 93 mid=(low+high)>>1; 94 mem(first,-1); 95 for(i=mm=0;i<m;i++) 96 if(l[i].len<=mid) 97 addedge(l[i].a,l[i].b); 98 t=dinic(1,n,mid); 99 if(t<k)low=mid+1; 100 else high=mid; 101 } 102 return low; 103 } 104 105 int main() 106 { 107 // freopen("in.txt","r",stdin); 108 int i; 109 while(~scanf("%d%d%d",&n,&m,&k)) 110 { 111 maxlen=-INF;minlen=INF; 112 for(i=0;i<m;i++){ 113 scanf("%d%d%d",&l[i].a,&l[i].b,&l[i].len); 114 if(l[i].len>maxlen)maxlen=l[i].len; 115 if(l[i].len<minlen)minlen=l[i].len; 116 } 117 118 printf("%d\n",binary()); 119 } 120 return 0; 121 }