Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 2995 | Accepted: 1065 |
Description
Input
Output
Sample Input
4 3 2 0 0 0 0 3 3 6 1 2 4 1 3 10 1 4 12 2 3 6 2 4 8 3 4 5 0
Sample Output
6
题意:有n个城镇,有的城镇里面有金矿,有的城镇里面有金库。第二行有n个数,代表第i个城镇里的金矿的存储量,第三行有n个数,代表第i个城镇里金库的容量。接下来有m条双向路径,每行输入三个数U,V,W,代表U和V之间的距离W。要求最长相邻距离中的最短距离。
思路:这个题由于是要求相邻距离的,所以不需要拆点。建图还是建立一个超级源点和 一个超级汇点,将金矿与源点相连,将金库与汇点相连。然后二分最大距离,小于二分的距离的连边,最后判断是否满流。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> #include <queue> #include <set> #include <map> using namespace std; const int inf=0x3f3f3f3f; int head[510],num[510],d[510],pre[510],cur[510],q[510]; int n,cnt,s,t,nv,sum; struct node { int u,v,cap; int next; } edge[1000010]; void add(int u, int v, int cap) { edge[cnt].v=v; edge[cnt].cap=cap; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].cap=cap; edge[cnt].next=head[v]; head[v]=cnt++; } void bfs() { memset(num,0,sizeof(num)); memset(d,-1,sizeof(d)); int f1=0, f2=0, i; q[f1++]=t; num[0]=1; d[t]=0; while(f1>=f2) { int u=q[f2++]; for(i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(d[v]!=-1) continue; d[v]=d[u]+1; num[d[v]]++; q[f1++]=v; } } } int isap() { memcpy(cur,head,sizeof(cur)); int flow=0, u=pre[s]=s, i; bfs(); while(d[s]<nv) { if(u==t) { int f=inf, pos; for(i=s; i!=t; i=edge[cur[i]].v) { if(f>edge[cur[i]].cap) { f=edge[cur[i]].cap; pos=i; } } for(i=s; i!=t; i=edge[cur[i]].v) { edge[cur[i]].cap-=f; edge[cur[i]^1].cap+=f; } flow+=f; if(flow>=sum) return flow; u=pos; } for(i=cur[u]; i!=-1; i=edge[i].next) { if(d[edge[i].v]+1==d[u]&&edge[i].cap) break; } if(i!=-1) { cur[u]=i; pre[edge[i].v]=u; u=edge[i].v; } else { if(--num[d[u]]==0) break; int mind=nv; for(i=head[u]; i!=-1; i=edge[i].next) { if(mind>d[edge[i].v]&&edge[i].cap) { mind=d[edge[i].v]; cur[u]=i; } } d[u]=mind+1; num[d[u]]++; u=pre[u]; } } return flow; } int main() { int m,i,j; int sum1; int u,v,w; int g[510],s1[510],mp[510][510]; while(~scanf("%d",&n)){ if(n==0) break; sum=sum1=0; for(i=1;i<=n;i++){ scanf("%d",&g[i]); sum+=g[i]; } for(i=1;i<=n;i++){ scanf("%d",&s1[i]); sum1+=s1[i]; } scanf("%d",&m); memset(mp,inf,sizeof(mp)); while(m--){ scanf("%d %d %d",&u,&v,&w); if(mp[u][v]>w) mp[u][v]=mp[v][u]=w; } if(sum1<sum){ printf("No Solution\n"); continue ; } int low=1,high=10010,mid; int ans=-1,x; while(low<=high){ mid=(low+high)/2; s=0; t=2*n+1; nv=t+1; cnt=0; memset(head,-1,sizeof(head)); for(i=1;i<=n;i++){ add(s,i,g[i]); add(i,t,s1[i]); for(j=1;j<i;j++){ if(mp[i][j]<=mid) add(i,j,inf); } } x=isap(); if(x>=sum){ ans=mid; high=mid-1; } else low=mid+1; } if(ans!=-1) printf("%d\n",ans); else printf("No Solution\n");; } return 0; }
POJ 3228-Gold Transportation(网络流_最大流+二分查找)
原文地址:http://blog.csdn.net/u013486414/article/details/43053005