bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分
Posted Kaiser
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分相关的知识,希望对你有一定的参考价值。
[Poi2010]Bridges
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1448 Solved: 510
[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
注意:通过桥为欧拉回路
Source
题解:二分风力值,然后最大流判断欧拉回路是否存在。
1 #include<queue> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 8 #define inf 1000000000 9 #define pa pair<int,int> 10 #define ll long long 11 #define mod 1000000007 12 using namespace std; 13 ll read() 14 { 15 ll x=0,f=1;char ch=getchar(); 16 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 17 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 18 return x*f; 19 } 20 21 int tot,n,m,cnt,T; 22 int mx,mn=inf; 23 int u[2005],v[2005],c[2005],d[2005],de[2005]; 24 int last[2005],q[2005],h[2005]; 25 struct edge{ 26 int to,next,v; 27 }e[1000005]; 28 29 void insert(int u,int v,int w) 30 { 31 e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w; 32 e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=0; 33 } 34 bool bfs() 35 { 36 int head=0,tail=1; 37 for(int i=0;i<=T;i++)h[i]=-1; 38 q[0]=0;h[0]=0; 39 while(head!=tail) 40 { 41 int now=q[head];head++; 42 for(int i=last[now];i;i=e[i].next) 43 if(e[i].v&&h[e[i].to]==-1) 44 { 45 h[e[i].to]=h[now]+1; 46 q[tail++]=e[i].to; 47 } 48 } 49 return h[T]!=-1; 50 } 51 int dfs(int x,int f) 52 { 53 if(x==T)return f; 54 int w,used=0; 55 for(int i=last[x];i;i=e[i].next) 56 if(h[e[i].to]==h[x]+1) 57 { 58 w=dfs(e[i].to,min(e[i].v,f-used)); 59 e[i].v-=w,e[i^1].v+=w; 60 used+=w;if(used==f)return f; 61 } 62 if(!used)h[x]=-1; 63 return used; 64 } 65 void build(int mid) 66 { 67 memset(last,0,sizeof(last));cnt=1; 68 memset(de,0,sizeof(de)); 69 tot=0; 70 for(int i=1;i<=m;i++) 71 { 72 if(c[i]<=mid)de[u[i]]--,de[v[i]]++; 73 if(d[i]<=mid)insert(v[i],u[i],1); 74 } 75 for(int i=1;i<=n;i++) 76 if(de[i]>0)tot+=de[i]/2,insert(0,i,de[i]/2); 77 else insert(i,T,-de[i]/2); 78 } 79 int dinic() 80 { 81 for(int i=1;i<=n;i++) 82 if(de[i]&1)return -1; 83 int ans=0; 84 while(bfs())ans+=dfs(0,inf); 85 return ans; 86 } 87 int main() 88 { 89 n=read();m=read();T=n+1; 90 for(int i=1;i<=m;i++) 91 { 92 u[i]=read(),v[i]=read(),c[i]=read(),d[i]=read(); 93 if(c[i]>d[i])swap(c[i],d[i]),swap(u[i],v[i]); 94 mn=min(mn,c[i]); 95 mx=max(mx,d[i]); 96 } 97 int l=mn,r=mx; 98 while(l<=r) 99 { 100 int mid=(l+r)>>1; 101 build(mid); 102 if(dinic()==tot) r=mid-1; 103 else l=mid+1; 104 } 105 if(l==mx+1)puts("NIE"); 106 else printf("%d\n",l); 107 }
以上是关于bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ2095[Poi2010]Bridges 动态加边网络流
bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分