BZOJ2095:[POI2010]Bridges(最大流,欧拉图)
Description
YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛。现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1。霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线。
Input
输入:第一行为两个用空格隔开的整数n(2<=n<=1000),m(1<=m<=2000),接下来读入m行由空格隔开的4个整数a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000),表示第i+1行第i座桥连接小岛a和b,从a到b承受的风力为c,从b到a承受的风力为d。
Output
输出:如果无法完成减肥计划,则输出NIE,否则第一行输出承受风力的最大值(要使它最小)
Sample Input
4 4
1 2 2 4
2 3 3 4
3 4 4 4
4 1 5 4
1 2 2 4
2 3 3 4
3 4 4 4
4 1 5 4
Sample Output
4
HINT
注意:通过桥为欧拉回路
Solution
首先二分一下答案,然后问题就变成了求混合图的欧拉回路。
这是网络流比较经典的一个问题,详细做法可以看这篇博客。
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<queue> 6 #define N (5009) 7 using namespace std; 8 9 struct Edge{int to,next,flow;}edge[N<<1]; 10 int n,m,a[N],b[N],c[N],d[N]; 11 int s,e=5000,tot,Depth[N],Deg[N]; 12 int head[N],num_edge; 13 queue<int>q; 14 15 void add(int u,int v,int l) 16 { 17 edge[++num_edge].to=v; 18 edge[num_edge].next=head[u]; 19 edge[num_edge].flow=l; 20 head[u]=num_edge; 21 } 22 23 int DFS(int x,int low) 24 { 25 if (x==e || !low) return low; 26 int f=0; 27 for (int i=head[x]; i; i=edge[i].next) 28 if (Depth[edge[i].to]==Depth[x]+1) 29 { 30 int Min=DFS(edge[i].to,min(low,edge[i].flow)); 31 edge[i].flow-=Min; 32 edge[((i-1)^1)+1].flow+=Min; 33 f+=Min; low-=Min; 34 if (!low) break; 35 } 36 if (!f) Depth[x]=-1; 37 return f; 38 } 39 40 bool BFS(int s,int e) 41 { 42 memset(Depth,0,sizeof(Depth)); 43 Depth[s]=1; q.push(s); 44 while (!q.empty()) 45 { 46 int x=q.front(); q.pop(); 47 for (int i=head[x]; i; i=edge[i].next) 48 if (!Depth[edge[i].to] && edge[i].flow) 49 { 50 Depth[edge[i].to]=Depth[x]+1; 51 q.push(edge[i].to); 52 } 53 } 54 return Depth[e]; 55 } 56 57 int Dinic(int s,int e) 58 { 59 int ans=0; 60 while (BFS(s,e)) ans+=DFS(s,0x7fffffff); 61 return ans; 62 } 63 64 bool check(int lim) 65 { 66 memset(head,0,sizeof(head)); 67 num_edge=0; 68 69 for (int i=1; i<=m; ++i) 70 { 71 if (c[i]>lim) return 0; 72 if (d[i]<=lim) add(a[i],b[i],1), add(b[i],a[i],0); 73 } 74 for (int i=1; i<=n; ++i) 75 { 76 if (Deg[i]<0) add(s,i,-Deg[i]/2), add(i,s,0); 77 if (Deg[i]>0) add(i,e,Deg[i]/2), add(e,i,0); 78 } 79 return Dinic(s,e)==tot/2; 80 } 81 82 int main() 83 { 84 scanf("%d%d",&n,&m); 85 for (int i=1; i<=m; ++i) 86 { 87 scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]); 88 if (c[i]>d[i]) swap(a[i],b[i]), swap(c[i],d[i]); 89 Deg[a[i]]--, Deg[b[i]]++; 90 } 91 for (int i=1; i<=n; ++i) 92 if (Deg[i]%2) {puts("NIE"); return 0;} 93 else tot+=abs(Deg[i]/2); 94 int l=1,r=1000,ans=-1; 95 while (l<=r) 96 { 97 int mid=(l+r)>>1; 98 if (check(mid)) ans=mid, r=mid-1; 99 else l=mid+1; 100 } 101 printf("%d\n",ans); 102 }