首页 > 代码库 > bzoj 2095 Poi2010 Bridges 混合图欧拉回路

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 }

 

bzoj 2095 Poi2010 Bridges 混合图欧拉回路