• [POJ1637]Sightseeing tour:混合图欧拉回路


    分析

    混合图欧拉回路问题。

    一个有向图有欧拉回路当且仅当图连通并且对于每个点,入度(=)出度。

    入度和出度相等可以联想到(我也不知道是怎么联想到的)网络流除了源汇点均满足入流(=)出流。于是可以考虑先将无向边随意定向后,通过网络流来调整无向边的方向以达到每个点的入度和出度相等的目的。

    建图方法如下:

    1. (outdeg[x]>indeg[x]),则从(S)(x)连一条容量为(frac{outdeg[x]-indeg[x]}{2})的边。

    2. (outdeg[x]<indeg[x]),则从(x)(T)连一条容量为(frac{indeg[x]-outdeg[x]}{2})的边。

    3. 将每一条你定向的有向边令其容量为(1)加入到网络中。

    这样一条增广路的意义就是将路径上的边全部取反,然后将第一个结点的入度(++),出度(--),将最后一个结点的入度(--),出度(++)

    怎么判无解?

    把所有边都看作无向边,那么如果存在一个节点的度数为奇数,直接输出impossible即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    #define rin(i,a,b) for(register int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[x];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=205;
    const int MAXM=1005;
    int n,m,S,T,maxflow,ecnt,head[MAXN];
    int indeg[MAXN],outdeg[MAXN],dep[MAXN],cur[MAXN];
    std::queue<int> q;
    struct Edge{
    	int to,nxt,cap;
    }e[MAXM*2+MAXN*2];
    
    inline void add_edge(int bg,int ed,int ca){
    	ecnt++;
    	e[ecnt].to=ed;
    	e[ecnt].nxt=head[bg];
    	e[ecnt].cap=ca;
    	head[bg]=ecnt;
    }
    
    inline bool bfs(){
    	memset(dep,0,sizeof dep);
    	rin(i,1,T) cur[i]=head[i];
    	while(!q.empty()) q.pop();
    	q.push(S);
    	dep[S]=1;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		trav(i,x){
    			int ver=e[i].to;
    			if(dep[ver]||!e[i].cap) continue;
    			dep[ver]=dep[x]+1;
    			q.push(ver);
    		}
    	}
    	return dep[T]>0;
    }
    
    int dfs(int x,int pref){
    	if(x==T||!pref) return pref;
    	int flow=0,temp;
    	for(int &i=cur[x];i;i=e[i].nxt){
    		int ver=e[i].to;
    		if(dep[ver]==dep[x]+1&&(temp=dfs(ver,std::min(pref,e[i].cap)))){
    			e[i].cap-=temp;
    			e[i^1].cap+=temp;
    			flow+=temp;
    			pref-=temp;
    			if(!pref) return flow;
    		}
    	}
    	return flow;
    }
    
    inline void dinic(){
    	while(bfs()) maxflow+=dfs(S,1e9);
    }
    
    int main(){
    	int TT=read();
    	while(TT--){
    		ecnt=1;memset(head,0,sizeof head);
    		memset(indeg,0,sizeof indeg);
    		memset(outdeg,0,sizeof outdeg);
    		maxflow=0; 
    		n=read(),m=read();S=n+1,T=S+1;
    		rin(i,1,m){
    			int u=read(),v=read(),typ=read();
    			if(!typ){
    				add_edge(u,v,1);
    				add_edge(v,u,0);
    				outdeg[u]++;
    				indeg[v]++;
    			}
    			else{
    				outdeg[u]++;
    				indeg[v]++;
    			}
    		}
    		bool flag=0;
    		rin(i,1,n){
    			flag|=((outdeg[i]+indeg[i])&1);
    		}
    		if(flag){
    			printf("impossible
    ");
    			continue;
    		}
    		int temp=0;
    		rin(i,1,n){
    			if(outdeg[i]>indeg[i]){
    				add_edge(S,i,(outdeg[i]-indeg[i])/2);
    				add_edge(i,S,0);
    				temp+=(outdeg[i]-indeg[i])/2;
    			}
    			else if(outdeg[i]<indeg[i]){
    				add_edge(i,T,(indeg[i]-outdeg[i])/2);
    				add_edge(T,i,0);
    			}
    		}
    		dinic();
    		if(maxflow<temp) printf("impossible
    ");
    		else printf("possible
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    yum添加网易和搜狐源
    [置顶] 写代码更轻松——动软
    再看Core Data中PSC陷入死锁的问题
    【Android框架进阶〖0〗】ThinkAndroid注解机制
    MetaQ安装部署文档
    Android打开WIFI或者移动网络的代码实现
    设计模式简介
    补全状态码避免再去搜:
    onreadystatechange 事件
    服务器常用的状态码及其对应的含义如下:
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10125549.html
Copyright © 2020-2023  润新知