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

传送门

这篇题解讲的真吼->这里

首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中

那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路

首先

无向图存在欧拉回路,当且仅当图的所有顶点度数都为偶数且图连通。

       有向图存在欧拉回路,当且仅当图的所有顶点入度等于出度且图连通。

那么我们怎么判断混合图的欧拉回路是否存在呢?

我们把无向边的边随便定向,然后计算每一个点的入度和出度。如果有某一个点的入度和出度之差是奇数,那么肯定不存在欧拉回路。

因为欧拉回路要求入度等于出度,也就是总度数为偶数,所以有奇数度点肯定不存在欧拉回路

那么现在每个点的入度和出度之差都是偶数,我们把它除以二,设为$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 ?

原文地址:https://www.cnblogs.com/bztMinamoto/p/9564911.html

时间: 2024-08-04 06:26:54

bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)的相关文章

【POJ1637】Sightseeing tour 混合图求欧拉回路存在性 网络流、

题意:多组数据,最后的0/1表示0无向1有向. 问是否存在欧拉回路. 题解:无向边给它任意定个向. 首先欧拉回路中点入度=出度. 然后发现每个无向边如果修改个方向,原来的入点的入度+1,出度-1,出点反之. 然后我们不妨对入度和出度不同的点跟源汇中之一连边,容量为入出度差一半(每改一条边差-2) 然后原来的无向边联系图中各点,容量1,最后check if(maxflow==sum差/4). 这都没看懂的弱菜们不妨出度多的连源,入度多的连汇,容量为入出度差一半,然后按无向边的定向给它在网络流图中定

POJ 1637 Sightseeing tour(混合图的欧拉回路)

题目链接 建个图,套个模板. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <algorithm> #include <vector> #include <string> #include <queue> using namespace std; #define INF 0x3ffffff str

poj1637 Sightseeing tour,混合图的欧拉回路问题,最大流解

混合图的欧拉回路问题 题目地址 欧拉回路问题 1 定义 欧拉通路 (Euler tour)--通过图中每条边一次且仅一次,并且过每一顶点的通路. 欧拉回路 (Euler  circuit)--通过图中每条边一次且仅一次,并且过每一顶点的回路. 欧拉图--存在欧拉回路的图.  2 无向图是否具有欧拉通路或回路的判定  G有欧拉通路的充分必要条件为:G 连通,G中只有两个奇度顶点(它们分别是欧拉通路的两个端点). G有欧拉回路(G为欧拉图):G连通,G中均为偶度顶点.  3 有向图是否具有欧拉通路或

欧拉回路、混合图的欧拉回路

欧拉回路 从一个点开始把图中的边恰好经过一次,再回到出发点,这样的路径就是欧拉回路. 如图就是一个欧拉回路 欧拉回路判定 不过怎么样的图中才存在欧拉回路呢? 欧拉回路分有向图和无向图两种: 有向图: 图中所有点的入度等于出度 无向图: 图中所有点的度数都为偶数 这还是很好理解的,不过你可能要问,怎么知道一个混合图中有没有欧拉回路呢? 混合图的欧拉回路 过程: 先将无向边随意定向 判断每个点的入度和出度是不是同奇偶,不同则无解 用一个超级原点向出度小于入度的点连一条容量为 \({|入度-出度| \

bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)

[题意] 给定n点m边的无向图,对于边u,v,从u到v边权为c,从v到u的边权为d,问能够经过每条边一次且仅一次的最小权值和. [思路] 二分答案mid,然后切断权值大于mid的边,原图就变成了一个既有无向边又有有向边的混合图,则问题转化为求混合图上是否存在一个欧拉回路. 无向图存在欧拉回路,当且仅当图的所有顶点度数都为偶数且图连通.      有向图存在欧拉回路,当且仅当图的所有顶点入度等于初度且图连通. 一条边仅经过一次,所以无向边最终的归属就是有向边,即我们要给无向边定向使存在欧拉回路.

BZOJ 2095 Poi2010 Bridges 二分答案+网络流

题目大意:给定一张图,每条边的两个方向有两个不同的权值,现在要求从1号节点出发遍历每条边一次且仅一次,最后回到1号节点,求最大边权的最小值 谁TM翻译的这道题给我滚出来看我不打死你 二分最大边的权值,然后就是经典的判断混合图欧拉回路存在性的问题了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 2020 #define S 0 #d

POJ 1637 混合图的欧拉回路判定

题意:一张混合图,判断是否存在欧拉回路. 分析参考: 混合图(既有有向边又有无向边的图)中欧拉环.欧拉路径的判定需要借助网络流! (1)欧拉环的判定:一开始当然是判断原图的基图是否连通,若不连通则一定不存在欧拉环或欧拉路径(不考虑度数为0的点). 其实,难点在于图中的无向边,需要对所有的无向边定向(指定一个方向,使之变为有向边),使整个图变成一个有向欧拉图(或有向半欧拉图).若存在一个定向满足此条件,则原图是欧拉图(或半欧拉图)否则不是.关键就是如何定向? 首先给原图中的每条无向边随便指定一个方

BZOJ2095 [Poi2010]Bridges

首先二分答案...然后这张图变成了有一些有向边,有一些无向边 然后就是混合图欧拉回路的判断 我们知道如果是有向图,它存在欧拉回路的等价条件是所有点的出度等于入度 对于混合图...先不管有向边,把无向边随意定向 首先要满足条件就是当前图的点的度数都是偶数,因为把一条边反向端点的出度入度之差改变了2,奇偶性不变 我们只要判断是否把部分已经定向的无向边反向以后可以满足度都是偶数这个条件 用网络流来判断 对于每条边,如果定向为$x$到$y$,则$y$向$x$连边,流量为1 对于每个点$x$,如果出度 -

Sightseeing tour (poj 1637 混合图的欧拉回路)

Language: Default Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7983   Accepted: 3346 Description The city executive board in Lund wants to construct a sightseeing tour by bus in Lund, so that tourists can see every co