bzoj2095: [Poi2010]Bridges(二分+混合圖求歐拉回路)

傳送門php

 

這篇題解講的真吼->這裏html

首先咱們能夠二分一個答案,而後把全部權值小於這個答案的都加入圖中ios

那麼問題就轉化爲一張混合圖(既有有向邊又有無向邊)中是否存在歐拉回路git

首先網絡

       無向圖存在歐拉回路,當且僅當圖的全部頂點度數都爲偶數且圖連通。spa

       有向圖存在歐拉回路,當且僅當圖的全部頂點入度等於出度且圖連通。code

那麼咱們怎麼判斷混合圖的歐拉回路是否存在呢?htm

咱們把無向邊的邊隨便定向,而後計算每個點的入度和出度。若是有某一個點的入度和出度之差是奇數,那麼確定不存在歐拉回路。blog

由於歐拉回路要求入度等於出度,也就是總度數爲偶數,因此有奇數度點確定不存在歐拉回路get

那麼如今每一個點的入度和出度之差都是偶數,咱們把它除以二,設爲$x$,那麼,對於每個點,咱們只要改變與它相連的$x$條邊的方向改變,它就能保證入度等於出度。若是每一個點都能這樣,那麼這張圖就存在一個歐拉回路

那麼咱們該改變哪些邊來讓點的出度等於入度呢?首先,有向邊不能改變,忽略。而後咱們一開始不是把無向邊定向了麼?那咱們就按照定的向構建網絡,邊長容量$1$。而後新建源點和匯點,若是入度大於出度,則將點向匯點連邊,容量爲$x$,若是出度大於入度,則將源點向該點連邊,容量爲$x$。而後咱們只要跑一個最大流,看看可否使網絡滿流。若能夠,則有解,不然無解

考慮爲何。咱們把網絡中每一條滿流的邊(也就是流量非0的邊)反向,就能獲得一個每點入度等於出度的歐拉圖。由於這個網絡滿流,因此每個入度大於出度的點都會有$x$條邊進來,把這$x$條邊反向就能使它入度等於出度。出度大於入度的點同理。那麼,既沒和源點連也沒和匯點連的點怎麼辦呢?由於這樣的點一定是入度等於出度的,那麼在網絡流過程當中他們屬於中間點,那麼一定知足流量守恆,因此進來的流量和出去的流量是同樣的,那麼反向以後仍然保持平衡

解決了

  1 //minamoto
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<queue>
  7 #define inf 0x3f3f3f3f
  8 using namespace std;
  9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 10 char buf[1<<21],*p1=buf,*p2=buf;
 11 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
 12 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
 13 inline int read(){
 14     #define num ch-'0'
 15     char ch;bool flag=0;int res;
 16     while(!isdigit(ch=getc()))
 17     (ch=='-')&&(flag=true);
 18     for(res=num;isdigit(ch=getc());res=res*10+num);
 19     (flag)&&(res=-res);
 20     #undef num
 21     return res;
 22 }
 23 const int N=5005,M=100005;
 24 int head[N],Next[M],ver[M],edge[M],tot;
 25 int out[N],in[N],u[N],v[N],w1[N],w2[N],sum;
 26 int dep[N],cur[N];
 27 int n,m,s,t;
 28 queue<int> q;
 29 inline void add(int u,int v,int e){
 30     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
 31     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;
 32 }
 33 bool bfs(){
 34     memset(dep,-1,sizeof(dep));
 35     while(!q.empty()) q.pop();
 36     for(int i=s;i<=t;++i) cur[i]=head[i];
 37     q.push(s),dep[s]=0;
 38     while(!q.empty()){
 39         int u=q.front();q.pop();
 40         for(int i=head[u];i;i=Next[i]){
 41             int v=ver[i];
 42             if(dep[v]<0&&edge[i]){
 43                 dep[v]=dep[u]+1,q.push(v);
 44                 if(v==t) return true;
 45             }
 46         }
 47     }
 48     return false;
 49 }
 50 int dfs(int u,int limit){
 51     if(u==t||!limit) return limit;
 52     int flow=0,f;
 53     for(int i=cur[u];i;i=Next[i]){
 54         int v=ver[i];cur[u]=i;
 55         if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){
 56             flow+=f,limit-=f;
 57             edge[i]-=f,edge[i^1]+=f;
 58             if(!limit) break;
 59         }
 60     }
 61     if(!flow) dep[u]=-1;
 62     return flow;
 63 }
 64 int dinic(){
 65     int flow=0;
 66     while(bfs()) flow+=dfs(s,inf);
 67     return flow;
 68 }
 69 bool check(int mid){
 70     memset(head,0,sizeof(head)),tot=1;
 71     memset(out,0,sizeof(out));
 72     memset(in,0,sizeof(in));
 73     sum=0;
 74     for(int i=1;i<=m;++i){
 75         if(w1[i]<=mid) ++out[u[i]],++in[v[i]];//有向邊記入度和出度 
 76         if(w2[i]<=mid) add(u[i],v[i],1);//無向邊隨便定個方向 
 77     }
 78     for(int i=1;i<=n;++i) if(abs(in[i]-out[i])&1) return false;
 79     for(int i=1;i<=n;++i){
 80         int x=in[i]-out[i];
 81         sum+=x>0?x>>1:0;
 82         if(x>0) add(i,t,x>>1);
 83         if(x<0) add(s,i,(-x)>>1);
 84     }
 85     return dinic()==sum;
 86 }
 87 int main(){
 88     //freopen("testdata.in","r",stdin);
 89     n=read(),m=read(),s=0,t=n+1;
 90     int l=inf,r=-inf;
 91     for(int i=1;i<=m;++i){
 92         u[i]=read(),v[i]=read(),w1[i]=read(),w2[i]=read();
 93         if(w1[i]>w2[i]) swap(u[i],v[i]),swap(w1[i],w2[i]);
 94         cmin(l,w1[i]),cmax(r,w2[i]);
 95     }
 96     while(l<=r){
 97         int mid=l+r>>1;
 98         if(check(mid)) r=mid-1;else l=mid+1;
 99     }
100     if(!check(l)) puts("NIE");else printf("%d\n",l);
101     return 0;
102 }
103 ?
相關文章
相關標籤/搜索