bzoj千题计划228:bzoj2095: [Poi2010]Bridges(欧拉回路、网络流、二分)
http://www.lydsy.com/JudgeOnline/problem.php?id=2095
二分答案,判断是否存在混合图的欧拉回路
如果只有一个方向的风力<=mid,这条边就是单向边
如果两个方向的风力都<=mid,这条边就是双向边
如果两个方向的风力都>mid,这条边不可能被经过,mid不合法
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 1003 #define M 6001 int n,m; struct node { int u,v,a,b; }e[2001]; int src,decc; int tot,front[N],nxt[M],to[M],cap[M]; int lev[N],cur[N]; queue<int>q; int d[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void add(int u,int v,int w) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w; to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=0; } bool bfs() { int now,t; for(int i=0;i<=decc;++i) lev[i]=-1,cur[i]=front[i]; lev[src]=0; q.push(src); while(!q.empty()) { now=q.front(); q.pop(); for(int i=front[now];i;i=nxt[i]) { t=to[i]; if(lev[t]==-1 && cap[i]) { lev[t]=lev[now]+1; q.push(t); } } } return lev[decc]!=-1; } int dinic(int now,int flow) { if(now==decc) return flow; int rest=0; int delta,t; for(int &i=cur[now];i;i=nxt[i]) { t=to[i]; if(lev[t]==lev[now]+1 && cap[i]) { delta=dinic(t,min(cap[i],flow-rest)); if(delta) { rest+=delta; cap[i]-=delta; cap[i^1]+=delta; if(rest==flow) break; } } } if(rest!=flow) lev[now]=-1; return rest; } bool check(int mid) { memset(d,0,sizeof(d)); for(int i=1;i<=m;++i) { if(e[i].a<=mid && e[i].b>mid) d[e[i].u]++,d[e[i].v]--; else if(e[i].b<=mid && e[i].a>mid) d[e[i].v]++,d[e[i].u]--; else if(e[i].a<=mid && e[i].b<=mid) d[e[i].u]++,d[e[i].v]--; else return false; } for(int i=1;i<=n;++i) if(d[i]&1) return false; int sum=0; tot=1; memset(front,0,sizeof(front)); for(int i=1;i<=n;++i) if(d[i]>0) add(src,i,d[i]/2),sum+=d[i]/2; else if(d[i]<0) add(i,decc,-d[i]/2); for(int i=1;i<=m;++i) if(e[i].a<=mid && e[i].b<=mid) add(e[i].u,e[i].v,1); int max_flow=0; while(bfs()) max_flow+=dinic(src,1e8); return max_flow==sum; } int main() { read(n); read(m); decc=n+1; for(int i=1;i<=m;++i) { read(e[i].u); read(e[i].v); read(e[i].a); read(e[i].b); } int l=1,r=1000,mid,ans=0; while(l<=r) { mid=l+r>>1; if(check(mid)) ans=mid,r=mid-1; else l=mid+1; } if(ans) printf("%d",ans); else printf("NIE"); return 0; }