1. 程式人生 > >POJ 2455 Secret Milking Machine 【二分】+【最大流】

POJ 2455 Secret Milking Machine 【二分】+【最大流】

<題目連結>

題目大意:

FJ有N塊地,這些地之間有P條雙向路,每條路的都有固定的長度l。現在要你找出從第1塊地到第n塊地的T條不同路徑,每條路徑上的路段不能與先前的路徑重複,問這些路徑中的最長路段的最小值是多少。

解題分析:

最小的最大值問題,依然需要用二分答案,枚舉出該最大路段的長度,然後將所有小於等於這個值得路段加入網路,將這些路段的容量置為1。因為是無向圖,所以正、反向弧的容量都置為1,之後跑一遍最大流,再根據最大流和T的大小關係來判斷。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4
#include <algorithm> 5 using namespace std; 6 7 #define INF 0x3f3f3f3f 8 #define mem(a,b) memset(a,b,sizeof(a)) 9 const int N=210; 10 11 struct Edge{ 12 int u,v,c; 13 }edge[N*N*2]; 14 15 struct Segment{ 16 int a,b,len; 17 }seg[N*N]; 18 19 int d[N],cur[N]; 20 int head[N],next[N*N*2
]; 21 int n,m,k,maxlen,minlen,cnt; 22 23 void addedge(int u,int v,int w){ 24 edge[cnt].u=u;edge[cnt].v=v,edge[cnt].c=w; 25 next[cnt]=head[u],head[u]=cnt++; 26 27 edge[cnt].u=v;edge[cnt].v=u,edge[cnt].c=w; 28 next[cnt]=head[v],head[v]=cnt++; 29 } 30 31 int bfs(int s,int t){
32 queue<int> q; 33 mem(d,0); 34 d[s]=1; 35 q.push(s); 36 while(!q.empty()){ 37 int x=q.front();q.pop(); 38 for(int i=head[x];i!=-1;i=next[i]){ 39 if(edge[i].c>0 && !d[edge[i].v]){ 40 d[edge[i].v]=d[x]+1; 41 q.push(edge[i].v); 42 } 43 } 44 } 45 return d[t]; 46 } 47 48 int dfs(int x,int a){ 49 if(x==n || a==0)return a; 50 int t,f,flow=0; 51 for(int& i=cur[x];i!=-1;i=next[i]){ 52 if(d[x]+1==d[edge[i].v] && (f=dfs(edge[i].v,min(a,edge[i].c)))>0){ 53 edge[i].c-=f; 54 edge[i^1].c+=f; 55 flow+=f; 56 a-=f; 57 if(!a)break; 58 } 59 } 60 return flow; 61 } 62 63 int dinic(int s,int t,int limit){ 64 int i,ret=0; 65 while(bfs(s,t)){ 66 for(i=1;i<=n;i++)cur[i]=head[i]; 67 ret+=dfs(s,INF); 68 } 69 return ret; 70 } 71 72 int binary_solve(){ 73 int low=minlen,high=maxlen; 74 while(low<high){ //這個二分答案部分對格式還是有點疑惑 75 int mid=(low+high)>>1; 76 cnt=0;mem(head,-1); //init() 77 for(int i=0;i<m;i++) //加入所有滿足要求的邊 78 if(seg[i].len<=mid) 79 addedge(seg[i].a,seg[i].b,1); 80 int t=dinic(1,n,mid); 81 if(t<k)low=mid+1; 82 else high=mid; 83 } 84 return low; 85 } 86 87 int main(){ 88 while(~scanf("%d%d%d",&n,&m,&k)){ 89 maxlen=-INF;minlen=INF; 90 for(int i=0;i<m;i++){ 91 scanf("%d%d%d",&seg[i].a,&seg[i].b,&seg[i].len); 92 maxlen=max(maxlen,seg[i].len); 93 minlen=min(minlen,seg[i].len); 94 } 95 printf("%d\n",binary_solve()); 96 } 97 return 0; 98 }

 

 

2018-11-24