算法问题描述
给定一个混合图,问是否存在一条欧拉回路
网络流
算法思想
混合图的欧拉回路涉及到无向边该往哪个方向选的问题,我们不妨先让无向边随意指向一个方向,并从u到v连1的边。
判断每个点的出度和入度(包括随机的无向边),如果出度已经等于入度了就不管它,如果有差值,对于每个点i记dw为出度-入度。dw>0则S到i连dw/2的边,dw<0则i到T连-dw/2的边,如果最大流能跑满则是欧拉回路,否则不是。
正确性
一个有向图是欧拉回路的充要条件是每个点出度等于入度
如果一个无向边决定翻转,那么它的起点和终点出入度的差值都会改变2,我们就在图里面连上容量1的边,出入度不等的点我们把它按情况和源汇点连dw/2的边,本质上是在重新分配那些无向边,如果无向边通过一些翻转(无向边有流量经过)使得出入度的差值被磨平(图被填满),则存在欧拉回路
代码
bool check(){
int sum=0;
memset(head,-1,sizeof head);
memset(ind,0,sizeof ind);
memset(oud,0,sizeof oud);
for(int i=1;i<=m;i++){
int u=p[i].u,v=p[i].v,a=p[i].a,b=p[i].b;
if(a && b){
oud[u]++;
ind[v]++;
ins(u,v,1);
}
else if(a){
oud[u]++;
ind[v]++;
}
else if(b){
ind[u]++;
oud[v]++;
}
else return 0;
}
for(int i=1;i<=n;i++){
int dw=oud[i]-ind[i];
if(dw&1) return 0;
if(dw>0) sum+=dw,ins(S,i,dw/2);
else ins(i,T,-dw/2);
}
return Dinic(S,T)==sum;
}