POJ 2391 Ombrophobic Bovines(floyd+二分+网络流)
http://poj.org/problem?id=2391
题意:N个区域,每个区域有一个避难所,现在每个区域有一定数量的牛,避难所可以容纳一定数量的牛,下雨的时所有的牛都找到避难所所需要的时间,如果有的牛不能找到避难所,输出-1。用费用流是错的,一个错误犯多次,或许是改变思维不容易吧。
网络流
1.源点到区域间连线,权值为现在区域牛的数量,区域到汇点连线,权值为可以容纳的牛的数量
2.然后floyd求出所有的点间的距离,然后二分答案,距离小于等于mid值的,连线。。。但是如果在原来的区域间连线,就会WA,因为如果mid=1, 1->2为1 , 2->3为1,
1->3为2的话,1->3不应该连线,但是如果连了1->2,2->3,那么1到3也是连通的,所以建图时把每个区域拆点
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstring> #define nMAX 1005 #define mMAX 210000 #define infl (long long)999999999*300 #define inf 1200 using namespace std; int head[nMAX],has[nMAX],contain[nMAX],level[nMAX],qu[nMAX]; long long map[nMAX][nMAX],high,low,mid; int n,s_edge,s,t; struct Edge { int u,v,cap,nxt; }edge[mMAX]; long long maxl(long long a,long long b) { return a>b?a:b; } long long minl(long long a,long long b) { return a<b?a:b; } int min(int a,int b) { return a<b?a:b; } void floyd() { int i,j,k; for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(map[i][k]==infl||map[k][j]==infl)continue; map[i][j]=minl(map[i][j],map[i][k]+map[k][j]); high=maxl(high,map[i][j]); } } void addedge(int u,int v,int cap) { s_edge++; edge[s_edge].v=v; edge[s_edge].cap=cap; edge[s_edge].nxt=head[u]; head[u]=s_edge; s_edge++; edge[s_edge].v=u; edge[s_edge].cap=0; edge[s_edge].nxt=head[v]; head[v]=s_edge; } int dfs(int x,int cap) { if(x==t)return cap; int temp=cap; for(int e=head[x];e;e=edge[e].nxt) { int v=edge[e].v; if(level[v]==level[x]+1&&temp>0&&edge[e].cap>0) { int tt=dfs(v,min(temp,edge[e].cap)); edge[e].cap-=tt; edge[e^1].cap+=tt; temp-=tt; } } return cap-temp; } bool bfs() { int beg,tail; for(int i=0;i<=t;i++)level[i]=-1; //memset(level,-1,sizeof(level)); beg=0,tail=1; qu[0]=0; level[0]=0; while(beg!=tail) { int u=qu[beg++]; for(int e=head[u];e;e=edge[e].nxt) { int v=edge[e].v; if(level[v]==-1&&edge[e].cap>0) { level[v]=level[u]+1; qu[tail++]=v; if(tail==nMAX)tail=0; } } if(beg==nMAX)beg=0; } if(level[t]==-1)return 0; return 1; } int dinic() { int SUM=0; while(bfs()) { SUM+=dfs(0,inf); } return SUM; } int main() { int x,y,i,j,p,num; long long w; while(~scanf("%d%d",&n,&p)) { num=0; for(i=1;i<=n;i++) { scanf("%d%d",&has[i],&contain[i]); num+=has[i]; } for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(i==j)map[i][j]=0; else map[i][j]=infl; } while(p--) { scanf("%d%d%lld",&x,&y,&w); map[y][x]=map[x][y]=minl(map[x][y],w); } low=0,high=0; floyd(); long long tt=++high; while(high>low) { mid=(high+low)/2; memset(head,0,sizeof(head)); s_edge=1; s=0,t=2*n+1; for(i=1;i<=n;i++) { addedge(s,i,has[i]); addedge(i+n,t,contain[i]); } for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(map[i][j]<=mid&&contain[j]>0) { addedge(i,j+n,inf); } } int a=dinic(); if(a>=num) { high=mid; } else low=mid+1; } if(low==tt)printf("-1\n"); else printf("%lld\n",high); } return 0; }