BZOJ 2095: [Poi2010]Bridges
Posted NeighThorn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2095: [Poi2010]Bridges相关的知识,希望对你有一定的参考价值。
2095: [Poi2010]Bridges
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 869 Solved: 299
[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
分析:
最大值最小的问题...
二分答案,然后就转化成了混合图欧拉回路的存在性问题...可以参考POJ 1637
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> //by NeighThorn #define inf 0x3f3f3f3f using namespace std; const int maxn=1000+5,maxm=10000+5; int n,m,S,T,tot,Min,Max,in[maxn],out[maxn],vis[maxm]; int cnt,hd[maxn],fl[maxm],to[maxm],pos[maxn],nxt[maxm]; struct M{ int x,y,c,d; }e[maxm]; inline void add(int x,int y,int s){ fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++; fl[cnt]=0;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++; } inline bool bfs(void){ memset(pos,-1,sizeof(pos)); int head=0,tail=0,q[maxn]; pos[S]=0;q[0]=S; while(head<=tail){ int top=q[head++]; for(int i=hd[top];i!=-1;i=nxt[i]) if(pos[to[i]]==-1&&fl[i]) pos[to[i]]=pos[top]+1,q[++tail]=to[i]; } return pos[T]!=-1; } inline int find(int v,int f){ if(v==T) return f; int res=0,t; for(int i=hd[v];i!=-1&&f>res;i=nxt[i]) if(pos[to[i]]==pos[v]+1&&fl[i]) t=find(to[i],min(fl[i],f-res)),res+=t,fl[i]-=t,fl[i^1]+=t; if(!res) pos[v]=-1; return res; } inline int dinic(void){ int res=0,t; while(bfs()) while(t=find(S,inf)) res+=t; return res; } inline bool check(int val){ cnt=0;tot=0; memset(in,0,sizeof(in)); memset(hd,-1,sizeof(hd)); memset(out,0,sizeof(out)); memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++){ if(e[i].c<=val) vis[i]+=1; if(e[i].d<=val) vis[i]+=2; } for(int i=1;i<=m;i++){ if(vis[i]==3) in[e[i].y]++,out[e[i].x]++,add(e[i].x,e[i].y,1); else if(vis[i]==1) in[e[i].y]++,out[e[i].x]++; else if(vis[i]==2) in[e[i].x]++,out[e[i].y]++; } for(int i=1;i<=n;i++) if(abs(in[i]-out[i])&1) return false; for(int i=1;i<=n;i++) if(in[i]<out[i]) add(S,i,(out[i]-in[i])/2),tot+=(out[i]-in[i])/2; else if(in[i]>out[i]) add(i,T,(in[i]-out[i])/2); if(dinic()==tot) return true; return false; } signed main(void){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif scanf("%d%d",&n,&m);Min=2333;Max=0;S=0,T=n+1; for(int i=1;i<=m;i++) scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].c,&e[i].d), Min=min(Min,min(e[i].c,e[i].d)), Max=max(Max,max(e[i].c,e[i].d)); int l=Min,r=Max,ans=-1; while(l<=r){ int mid=(l+r)>>1; if(check(mid)) ans=mid,r=mid-1; else l=mid+1; } if(ans==-1) puts("NIE"); else printf("%d\\n",ans); return 0; }
By NeighThorn
以上是关于BZOJ 2095: [Poi2010]Bridges的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ2095[Poi2010]Bridges 动态加边网络流
bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分