HDU 1878 欧拉回路
2016-03-05 00:16
465 查看
题意:
欧拉回路的判断条件,
一、无向图
每个顶点的度数都是偶数,则存在欧拉回路。
二、有向图(所有边都是单向的)
每个节顶点的入度都等于出度,则存在欧拉回路。
以上两种情况都很好理解。其原理就是每个顶点都要能进去多少次就能出来多少次。
三、混合图(有的边是单向的,有的边是无向的。常被用于比喻城市里的交通网络,有的路是单行道,有的路是双行道。)
找到一个给每条无向的边定向的策略,使得每个顶点的入度等于出度,这样就能转换成上面第二种情况。这就可以转化成一个二部图最大匹配问题。网络模型如下:
新建一个图。
对于原图中每一条无向边i,在新图中建一个顶点e(i);
对于原图中每一个顶点j,在新图中建一个顶点v(j)。
如果在原图中,顶点j和k之间有一条无向边i,那么在新图中从e(i)出发,添加两条边,分别连向v(j)和v(k),容量都是1。
在新图中,从源点向所有e(i)都连一条容量为1的边。
对于原图中每一个顶点j,它原本都有一个入度in、出度out和无向度un。显然我们的目的是要把所有无向度都变成入度或出度,从而使它的入度等于总度数的一半,也就是(in + out + un) / 2(显然与此同时出度也是总度数的一半,如果总度数是偶数的话)。当然,如果in已经大于总度数的一半,或者总度数是奇数,那么欧拉回路肯定不存大。如果in小于总度数的一半,并且总度数是偶数,那么我们在新图中从v(j)到汇点连一条边,容量就是(in + out + un) / 2 – in,也就是原图中顶点j还需要多少入度。
按照这个网络模型算出一个最大流,如果每条从v(j)到汇点的边都达到满流量的话,那么欧拉回路成立。
代价:
欧拉回路的判断条件,
一、无向图
每个顶点的度数都是偶数,则存在欧拉回路。
二、有向图(所有边都是单向的)
每个节顶点的入度都等于出度,则存在欧拉回路。
以上两种情况都很好理解。其原理就是每个顶点都要能进去多少次就能出来多少次。
三、混合图(有的边是单向的,有的边是无向的。常被用于比喻城市里的交通网络,有的路是单行道,有的路是双行道。)
找到一个给每条无向的边定向的策略,使得每个顶点的入度等于出度,这样就能转换成上面第二种情况。这就可以转化成一个二部图最大匹配问题。网络模型如下:
新建一个图。
对于原图中每一条无向边i,在新图中建一个顶点e(i);
对于原图中每一个顶点j,在新图中建一个顶点v(j)。
如果在原图中,顶点j和k之间有一条无向边i,那么在新图中从e(i)出发,添加两条边,分别连向v(j)和v(k),容量都是1。
在新图中,从源点向所有e(i)都连一条容量为1的边。
对于原图中每一个顶点j,它原本都有一个入度in、出度out和无向度un。显然我们的目的是要把所有无向度都变成入度或出度,从而使它的入度等于总度数的一半,也就是(in + out + un) / 2(显然与此同时出度也是总度数的一半,如果总度数是偶数的话)。当然,如果in已经大于总度数的一半,或者总度数是奇数,那么欧拉回路肯定不存大。如果in小于总度数的一半,并且总度数是偶数,那么我们在新图中从v(j)到汇点连一条边,容量就是(in + out + un) / 2 – in,也就是原图中顶点j还需要多少入度。
按照这个网络模型算出一个最大流,如果每条从v(j)到汇点的边都达到满流量的话,那么欧拉回路成立。
代价:
[code]// // Created by CQU_CST_WuErli // Copyright (c) 2016 CQU_CST_WuErli. All rights reserved. // #include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <cctype> #include <cmath> #include <string> #include <vector> #include <list> #include <map> #include <queue> #include <stack> #include <set> #include <algorithm> #include <sstream> #define CLR(x) memset(x,0,sizeof(x)) #define OFF(x) memset(x,-1,sizeof(x)) #define MEM(x,a) memset((x),(a),sizeof(x)) #define BUG cout << "I am here" << endl #define lookln(x) cout << #x << "=" << x << endl #define SI(a) scanf("%d",&a) #define SII(a,b) scanf("%d%d",&a,&b) #define SIII(a,b,c) scanf("%d%d%d",&a,&b,&c) #define rep(flag,start,end) for(int flag=start;flag<=end;flag++) #define Rep(flag,start,end) for(int flag=start;flag>=end;flag--) #define Lson l,mid,rt<<1 #define Rson mid+1,r,rt<<1|1 #define Root 1,n,1 const int INF_INT=0x3f3f3f3f; const long long INF_LL=0x7fffffff; const int MOD=1e9+7; const double eps=1e-9; const double pi=acos(-1); typedef long long ll; using namespace std; const int N=1010; int n,m; vector<int> g ; int vis ; int deg ; void dfs(int u) { vis[u]=1; for (int i=0;i<g[u].size();i++){ int v=g[u][i]; if (vis[v]) continue; dfs(v); } } int main(int argc, char const *argv[]) { #ifdef LOCAL freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin); // freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout); #endif while(SII(n,m)==2 && n) { CLR(deg); rep(i,1,n) g[i].clear(); rep(i,1,m) { int u,v; SII(u,v); g[u].push_back(v); g[v].push_back(u); deg[u]++;deg[v]++; } int ans=1; CLR(vis); dfs(1); rep(i,1,n) if (!vis[i]) ans=0; int cnt=0; rep(i,1,n) if (deg[i]%2==1) cnt++; if (cnt) ans=0; cout << ans << endl; } return 0; }
相关文章推荐
- 查找当前目录下文件中包含关键字符串的文件以及行号
- alternating minmize算法
- Shibboleth
- POJ1860-Currency Exchange-判正环
- Android开发60需要注意的问题
- 在eclipse项目下点击Build path出现No action available的错误
- 让AllocateHwnd接受一般函数地址作参数(105篇博客)
- 自助去除APK的广告!(整理、修改、简化版)
- DDL、DML和DCL的理解
- UVA 11324 The Largest Clique(SCC+dp)
- Ajax实现定时从服务器获取数据,定时更新数据
- week1:个人博客作业
- codeforce344 C report
- TMsgThread, TCommThread -- 在delphi线程中实现消息循环(105篇博客,好多研究消息的文章)
- codeforces 631C C. Report
- Hadoop日志文件分析系统
- 人生第一次
- 在界面线程不能使用Sleep和WaitForSingleObject之类的函数, 使用 MsgWaitForMultipleObjects
- Android下设置drawableleft导入的图片大小
- 今天算是把变量提升给整明白了