算法复习——欧拉回路(uoj117)
题目:
题解:
欧拉回路相关定理(相关定义和证明请参见其他资料):
1.欧拉回路
(1)有向图:所有点的出度都等于入度为该图为欧拉图(存在欧拉回路)的充要条件。
(2)无向图:所有点的度都为偶数为该图为欧拉图(存在欧拉回路)的充要条件。
2.欧拉通路
(1)有向图:除两点(其中一点出度+1==入度,另一点入度+1==出度)另外点出度都等于入度为该图为半欧拉图(存在欧拉通路)的充要条件。
(2)无向图:除两点(两点度都为奇数)另外点的度都为偶数为该图为半欧拉图(存在欧拉通路)的充要条件。
以上定理用于判断是否为存在欧拉回路或者通路
接下来是两个推论:
嗯就是这样··再回到这道题上,一道很裸地模版题···然而被uoj大佬的数据教做人··
注意判定重边不然就会超时·····用类似于网络流的cur来优化(具体见代码)
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=1e5+5; const int M=5e5+5; int first[N],go[M*2],next[M*2],tot=0; int n,m,T,ru[N],chu[N],stack[M*2],cnt; bool visit[M]; inline void comb(int a,int b) { next[++tot]=first[a],first[a]=tot,go[tot]=b; } inline void dfs1(int u) { for(int &e=first[u];e;e=next[e]) { if(!visit[e]) { visit[e]=true; if(e%2==1) visit[e+1]=true; else visit[e-1]=true; int t=e; dfs1(go[e]); stack[++cnt]=t; } } } inline void dfs2(int u) { for(int &e=first[u];e;e=next[e]) { if(!visit[e]) { visit[e]=true; int t=e; dfs2(go[e]); stack[++cnt]=t; } } } int main() { //freopen("a.in","r",stdin); scanf("%d",&T); int a,b; scanf("%d%d",&n,&m); if(T==1) //无向图情况 { for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); comb(a,b); comb(b,a); ru[b]++; chu[a]++; } for(int i=1;i<=n;i++) if((ru[i]+chu[i])%2==1) { cout<<"NO"<<endl; return 0; } for(int i=1;i<=n;i++) { if(first[i]) { dfs1(i); break; } } if(cnt!=m) { cout<<"NO"<<endl; return 0; } cout<<"YES"<<endl; for(int i=cnt;i>=1;i--) { if(stack[i]%2==1) cout<<(stack[i]+1)/2<<" "; else cout<<stack[i]/2*(-1)<<" "; } return 0; } else { for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); comb(a,b); ru[b]++; chu[a]++; } for(int i=1;i<=n;i++) if(ru[i]!=chu[i]) { cout<<"NO"<<endl; return 0; } for(int i=1;i<=n;i++) { if(first[i]) { dfs2(i); break; } } if(cnt!=m) { cout<<"NO"<<endl; return 0; } cout<<"YES"<<endl; for(int i=cnt;i>=1;i--) cout<<stack[i]<<" "; return 0; } }