[BZOJ2095][Poi2010]Bridges 二分+网络流
2095: [Poi2010]Bridges
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1187 Solved: 408
[Submit][Status][Discuss]
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
注意:通过桥为欧拉回路
首先我们二分答案,之后我们用可行边建图,发现是混合图的欧拉回路问题,用网络流解决。
对于无向边,我们给它随意定向,之后看每个点的入度出度之差的绝对值tmp是否为2的倍数。
对于入度大于出度的点,我们从这个点向汇点连一条容量为tmp/2的边。
对于入度小于出度的点,我们从源点向这个点连一条容量为tmp/2的边。
对于每一条无向边,我们沿定的向连一条容量为1的边。
查询是否满流。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 int n,m; 9 int head[2002],cnt; 10 struct data { 11 int to,next,w; 12 }e[80008]; 13 void add(int u,int v,int c){e[cnt].to=v;e[cnt].next=head[u];e[cnt].w=c;head[u]=cnt++;} 14 struct data1 { 15 int a,b,c,d; 16 }t[2002]; 17 int ru[2002],cu[2002]; 18 int q[2002]; 19 bool vis[2002]; 20 int dis[2002]; 21 bool bfs() { 22 memset(dis,-1,sizeof(dis)); 23 int h=0,t=1; 24 q[h]=0; 25 vis[0]=1; 26 dis[0]=0; 27 while(h!=t) { 28 int now=q[h];h++;vis[now]=0;if(h==2000) h=0; 29 for(int i=head[now];i>=0;i=e[i].next) { 30 int to=e[i].to; 31 if(e[i].w>0&&dis[to]<0) { 32 dis[to]=dis[now]+1; 33 if(!vis[to]){ 34 vis[to]=1; 35 q[t++]=to;if(t==2000)t=0; 36 } 37 } 38 } 39 } 40 return dis[n+1]!=-1; 41 } 42 int dfs(int now,int a) { 43 if(now==n+1||a==0) return a; 44 int flow=0,f; 45 for(int i=head[now];i>=0;i=e[i].next) { 46 int to=e[i].to; 47 if(dis[to]==dis[now]+1&&e[i].w>0) { 48 f=dfs(to,min(a,e[i].w)); 49 e[i].w-=f; 50 e[i^1].w+=f; 51 flow+=f; 52 a-=f; 53 if(a==0) break; 54 } 55 } 56 if(!flow) dis[now]=-1; 57 return flow; 58 } 59 bool check(int mid) { 60 cnt=0; 61 memset(head,-1,sizeof(head)); 62 memset(ru,0,sizeof(ru)); 63 memset(cu,0,sizeof(cu)); 64 for(int i=1;i<=m;i++) { 65 if(t[i].c<=mid) { 66 if(t[i].d<=mid) { 67 add(t[i].a,t[i].b,1); 68 add(t[i].b,t[i].a,0); 69 cu[t[i].a]++;ru[t[i].b]++; 70 } 71 else {cu[t[i].a]++;ru[t[i].b]++;} 72 } 73 else if(t[i].d<=mid) {ru[t[i].a]++;cu[t[i].b]++;} 74 else return 0; 75 } 76 int sum=0; 77 for(int i=1;i<=n;i++) { 78 if(abs(ru[i]-cu[i])&1) return 0; 79 int tmp=abs(ru[i]-cu[i]); 80 if(ru[i]<cu[i]) {add(0,i,tmp/2);add(i,0,0);} 81 else if(ru[i]>cu[i]) {sum+=tmp/2;add(i,n+1,tmp/2);add(n+1,i,0);} 82 } 83 int ans=0; 84 while(bfs()){ans+=dfs(0,2147483647);} 85 return ans==sum; 86 } 87 int main() { 88 scanf("%d%d",&n,&m); 89 for(int i=1;i<=m;i++) { 90 scanf("%d%d%d%d",&t[i].a,&t[i].b,&t[i].c,&t[i].d); 91 } 92 int l=0,r=1000; 93 while(l<=r) { 94 int mid=(l+r)>>1; 95 if(check(mid)) r=mid-1; 96 else l=mid+1; 97 } 98 if(r==1000) printf("NIE"); 99 else printf("%d",r+1); 100 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~