poj2391 最大流+拆点
题意:F块草坪,上面有n头牛,可以容纳m个牛遮雨。将草坪一份为2,成为二部图。
对于此题,和poj2112很像,只是2112很明显的二部图。这道题就开始敲,但是建图遇到问题,草坪的2个值怎么处理,于是将1个草坪分成2分,一份与源点相连,值为牛的个数,
另一份与汇点相连表示可以留下多少牛,由于是一个草坪,所以这两份之间相连,容量无穷大。然后对于能够相通的2块草坪,由当前块草坪左边部分,向相连的连(前提时间小于二分的时间),容量无穷。二分答案。
#include<stdio.h> #include<string.h> #include<queue> #define maxn 600 #define INF 10000000000000 #define LL __int64 using namespace std; int vis[maxn],n,m,c[maxn],f[maxn],fn; LL map[maxn][maxn],dis[maxn][maxn]; LL min(LL x,LL y) {return x<y?x:y;} LL max(LL x,LL y) {return x>y?x:y;} void init() { int i,j; for(i=1;i<=fn;i++) { for(j=1;j<=fn;j++) { if(i==j) dis[i][j]=0; else dis[i][j]=INF; } } } void floyd() { int i,j,k; for(k=1;k<=fn;k++) for(i=1;i<=fn;i++) for(j=1;j<=fn;j++) { if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j]; } /*for(i=1;i<=fn;i++) { for(j=1;j<=fn;j++) { printf("%d ",dis[i][j]); } printf("\n"); }*/ } void makemap(LL maxval) { int i,j; memset(map,0,sizeof(map)); for(i=1;i<=fn;i++) { map[0][i]=c[i]; } for(i=1;i<=fn;i++) map[i+fn][n+1]=f[i]; for(i=1;i<=fn;i++) map[i][i+fn]=INF; for(i=1;i<=fn;i++) { for(j=1;j<=fn;j++) { if(i==j) continue; if(dis[i][j]<=maxval) { map[i][j+fn]=INF; } } } /*for(i=0;i<=n+1;i++) { for(j=0;j<=n+1;j++) { printf("%d ",map[i][j]); } printf("\n"); }*/ } int BFS() { int i,j; queue<int>q; memset(vis,-1,sizeof(vis)); vis[0]=0; q.push(0); while(!q.empty()) { int t=q.front(); q.pop(); for(i=0;i<=n+1;i++) { if(vis[i]<0&&map[t][i]) { vis[i]=vis[t]+1; q.push(i); } } } if(vis[n+1]>0) return 1; return 0; } LL dfs(int u,LL low) { int i,j; LL a; if(u==n+1) return low; for(i=0;i<=n+1;i++) { if(vis[i]==vis[u]+1&&map[u][i]) { a=(LL)dfs(i,min(low,map[u][i])); if(!a)continue; map[u][i]-=a; map[i][u]+=a; return a; } } return 0; } int main() { int i,j,num; LL maxval; while(scanf("%d%d",&fn,&m)!=EOF) { num=0; maxval=0; for(i=1;i<=fn;i++) { scanf("%d%d",&c[i],&f[i]); num+=c[i]; } n=fn*2; init(); for(i=0;i<m;i++) { LL x,y,z; scanf("%I64d %I64d %I64d",&x,&y,&z); if(dis[x][y]>z) { dis[y][x]=z; dis[x][y]=z; } } floyd(); for(i=1;i<=fn;i++) { for(j=1;j<=fn;j++) { if(dis[i][j]!=INF) maxval=max(maxval,dis[i][j]); } } LL l=0,r=maxval,ans=-1; while(l<=r) { LL ret=0; LL mid=(l+r)/2; makemap(mid); while(BFS()) { while(1) { LL a=dfs(0,INF); if(!a)break; ret+=a; } } //printf("%d ",mid); if(ret>=num) { ans=mid; r=mid-1; } else l=mid+1; } printf("%I64d\n",ans); } }