bzoj 2095 Poi2010 Bridges 混合图欧拉回路
二分答案后变为判定混合图是否存在欧拉回路。
有向图存在欧拉回路的条件是连通且每个点的入=出。
把混合图先变为有向图后再修改。
首先把每条无向边定向,再在最大流图中建一条与定的方向反的流量为1的边。
每个点的 d=出度-入度 必须是偶数,因为把一条边反向后这个东西至少会会改变2.
然后由S向 d<0的连流量-d/2的边,d>0的向T连d/2的边。
有欧拉回路的条件是满流.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define inf 0x3f3f3f3f 7 #define N 2005 8 #define M 100005 9 using namespace std; 10 int head[N],ver[M],f[M],nxt[M],tot; 11 void add(int a,int b,int c) 12 { 13 c=abs(c); 14 tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;f[tot]=c; 15 tot++;nxt[tot]=head[b];head[b]=tot;ver[tot]=a;f[tot]=0; 16 return ; 17 } 18 int ch[N],S,T; 19 queue<int>q; 20 bool tell() 21 { 22 memset(ch,-1,sizeof(ch)); 23 q.push(S);ch[S]=0; 24 while(!q.empty()) 25 { 26 int tmp=q.front();q.pop(); 27 for(int i=head[tmp];i;i=nxt[i]) 28 { 29 if(ch[ver[i]]==-1&&f[i]) 30 { 31 ch[ver[i]]=ch[tmp]+1; 32 q.push(ver[i]); 33 } 34 } 35 } 36 return ch[T]!=-1; 37 } 38 int zeng(int a,int b) 39 { 40 if(a==T)return b; 41 int r=0; 42 for(int i=head[a];i&&b>r;i=nxt[i]) 43 { 44 if(f[i]&&ch[ver[i]]==ch[a]+1) 45 { 46 int t=zeng(ver[i],min(f[i],b-r)); 47 f[i]-=t;f[i^1]+=t;r+=t; 48 } 49 } 50 if(!r)ch[a]=-1; 51 return r; 52 } 53 int dinic() 54 { 55 int r=0,t; 56 while(tell())while(t=zeng(S,inf))r+=t; 57 return r; 58 } 59 int bian[2005][4]; 60 int n,m; 61 int fa[2005]; 62 int find(int x) 63 { 64 if(x==fa[x])return x; 65 return fa[x]=find(fa[x]); 66 } 67 int du[N]; 68 bool pan(int x) 69 { 70 tot=1; 71 memset(head,0,sizeof(head)); 72 memset(du,0,sizeof(du)); 73 S=0;T=n+1; 74 for(int i=1;i<=n;i++)fa[i]=i; 75 for(int i=1;i<=m;i++) 76 { 77 int xx=bian[i][0],yy=bian[i][1]; 78 if(bian[i][3]<=x||bian[i][2]<=x) 79 { 80 if(bian[i][2]<=x) 81 { 82 du[xx]++;du[yy]--; 83 if(bian[i][3]<=x) 84 { 85 add(yy,xx,1); 86 } 87 } 88 else 89 { 90 du[xx]--;du[yy]++; 91 } 92 int aa=find(xx),bb=find(yy); 93 if(aa!=bb)fa[aa]=bb; 94 } 95 } 96 for(int i=2;i<=n;i++)if(find(i)!=find(i-1))return 0; 97 int now=0; 98 for(int i=1;i<=n;i++) 99 { 100 if(du[i]%2!=0)return 0; 101 if(du[i]<0) 102 { 103 add(S,i,du[i]/2); 104 now-=du[i]/2; 105 } 106 else add(i,T,du[i]/2); 107 } 108 return dinic()==now; 109 } 110 int main() 111 { 112 scanf("%d%d",&n,&m); 113 int mn=inf,mx=0; 114 for(int i=1;i<=n;i++)fa[i]=i; 115 for(int i=1;i<=m;i++) 116 { 117 scanf("%d%d%d%d",&bian[i][0],&bian[i][1],&bian[i][2],&bian[i][3]); 118 mn=min(mn,bian[i][2]);mx=max(mx,bian[i][2]); 119 mn=min(mn,bian[i][3]);mx=max(mx,bian[i][3]); 120 } 121 int l=mn,r=mx; 122 while(l<=r) 123 { 124 int mid=(l+r)>>1; 125 if(pan(mid))r=mid-1; 126 else l=mid+1; 127 } 128 if(l==mx+1)puts("NIE"); 129 else printf("%d\n",l); 130 return 0; 131 }