LOJ-10105(欧拉回路模板,套圈法,递归)
题目链接:传送门
思路:
(1)用邻接表存储有向图和无向图,有向图和无向图的每条边均站两个单元,无向图有正向边和反向边的区分。
(2)有向图有欧拉回路:所有点的入度=出度;
无向图有欧拉回路:所有点的度数之和是2的倍数。
(3)搜索时要从存在的点开始搜索,注意每条边站两个单位,所以i/2。
(4)搜索的结果路径必须包含所有边,如果图不连通则不行。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn = 200200; struct Node{ int to,next,val; }edge[maxn*2]; int vis[maxn],head[maxn],IN[maxn],OUT[maxn],tot; vector <int> ans; void Init() { memset(vis,0,sizeof(vis)); memset(head,0,sizeof(head)); memset(IN,0,sizeof(IN)); memset(OUT,0,sizeof(OUT)); tot=2;ans.clear(); } void addedge(int u,int v,int w) { edge[tot].to=v; edge[tot].next=head[u]; edge[tot].val=w; head[u]=tot++; } void dfs(int u) { for(int &i=head[u];i;i=edge[i].next){ //对i引用,提高速度 Node tmp=edge[i]; if(!vis[i>>1]){ vis[i>>1]=1; dfs(tmp.to); ans.push_back(tmp.val); } } } int main(void) { int n,m,i,j,x,y,type,fg=1; scanf("%d%d%d",&type,&n,&m); Init(); for(i=1;i<=m;i++){ scanf("%d%d",&x,&y); addedge(x,y,i); IN[y]++;OUT[x]++; if(type==1) addedge(y,x,-i); else tot++; } if(type==1){ for(i=1;i<=n;i++) if((IN[i]+OUT[i])%2){ fg=0;break; } }else{ for(i=1;i<=n;i++) if(IN[i]!=OUT[i]){ fg=0;break; } } if(fg){ for(i=1;i<=n;i++) //找到图中存在的点 if(head[i]){ dfs(i);break; } if(ans.size()!=m) printf("NO\n"); else{ printf("YES\n"); for(i=m-1;i>=0;i--){ if(i!=m-1) printf(" "); printf("%d",ans[i]); //ans相当于栈,所以倒叙输出 } } }else printf("NO\n"); return 0; }
参考文章:传送门