3 solutions
-
8
题意
判断一个有向图是否有欧拉路径(一笔画),有就按字典序小输出,没有就输出
No
思路
欧拉路径:一笔画的路线
按字典序小输出,先排序
然后判断是否有欧拉路径,由于是有向图,所以判断方法为:[1]
- 起点和终点是同一点:所有点的出度与入度相等
- 起点和终点不是同一点:仅有一个点出度比入度多 (起点),且仅有一个点入度比出度多 (终点)
不满足以上要求就没有欧拉路径,输出
No
输出路径:见课件 P30[2]
代码
#include <bits/stdc++.h> using namespace std; const int N = 100005,M = 100005; vector<int> a[N]; int e[N]; // 第 i 个点排到第几条边(在 a 里的)了 int ind[N],outd[N]; stack<int> s; void dfs(int n){ for (int i = e[n];i < a[n].size();i = e[n]){ e[n] = i + 1; dfs(a[n][i]); } s.push(n); } int main(int argc, char **argv){ int n,m; cin >> n >> m; for (int i = 0;i < m;i++){ int u,v; cin >> u >> v; a[u].push_back(v); ind[v]++; outd[u]++; } // 判断是否为欧拉路 int st = 1,stf(0),ef(0);bool f(0); for (int i = 1;i <= n;i++){ if (ind[i] != outd[i]){ f = 1; // 出度多 1,起点 if (ind[i] == outd[i] - 1) stf++,st = i; // 入度多 1,终点 else if (ind[i] - 1 == outd[i]) ef++; else{ printf("No"); return 0; } } } if (f/*欧拉回路*/ && (stf != 1 && ef != 1)/*欧拉通路*/){ printf("No"); return 0; } // 字典序 for(int i = 1;i <= n;i++){ sort(a[i].begin(),a[i].end()); } dfs(st); while(!s.empty()){ printf("%d ",s.top()); s.pop(); } return 0; }
参考与鸣谢
参考了老师的课件
-
5
#include<bits/stdc++.h> using namespace std; vector<int>g[200001]; int dr[200001]; int dc[200001]; stack<int>q; int vis[200001]; void ol(int a){ int sz=g[a].size(); for(int i=vis[a];i<sz;i=vis[a]){ vis[a]=i+1; ol(g[a][i]); } q.push(a); } int u[200001]; int v[200001]; int main(){ int n,m,s=1,r1=0,r2=0,f=0; cin>>n>>m; for(int i=1;i<=m;i++){ int u1,v1; cin>>u1>>v1; u[i]=u1; v[i]=v1; dc[u1]++; dr[v1]++; g[u1].push_back(v1); } for(int i=1;i<=n;i++){ sort(g[i].begin(),g[i].end()); } for(int i=1;i<=n;i++){ if(dc[i]-dr[i]==1){ s=i; break; } } for(int i=1;i<=n;i++){ if(dr[i]-dc[i]==1){ r1++; if(r1>1){ cout<<"No"; return 0; } else{ continue; } } if(dc[i]-dr[i]==1){ r2++; if(r2>1){ cout<<"No"; return 0; } else{ continue; } } if(dc[i]!=dr[i]){ f=1; } } if(f==1){ cout<<"No"; return 0; } ol(s); while(!q.empty()){ cout<<q.top()<<" "; q.pop(); } }
-
-1
题意
为了找到有向图中字典序最小 初始化一些全局变量,包括访问标记数组 vis、邻接表 G、入度数组 ru、最近访问位置数组 newest 和一个栈 ans 用于存储最终的欧拉路径。
读取输入,建立有向图的邻接表表示,并计算每个节点的入度。
检查图中是否存在欧拉路径的条件:所有节点的入度和出度之差为0或1,且只有一个节点的入度和出度之差为1(起始点),只有一个节点的入度和出度之差为-1(结束点)。如果不满足这些条件,则输出 "No" 并返回。
找到一个可能的起始点(即入度比出度少1的节点),如果没有这样的节点,则从任意节点开始。
使用深度优先搜索(DFS)遍历图,同时在遍历时记录访问过的边的位置,以便回溯时可以继续未完成的遍历。
在DFS过程中,每次访问完一个节点的所有邻居后,将该节点压入栈中。
最后,如果找到了欧拉路径,则将栈中的元素依次弹出并输出,得到字典序最小的欧拉路径。
请注意,这段代码假设输入的图是连通的,且满足欧拉路径存在的条件。如果图不连通或者不满足欧拉路径的条件 请修改 #何云锐置顶位#好评有置顶
代码
#include<bits/stdc++.h> using namespace std; int vis[100005]={0}; vector<int> G[100005]; int ru[100005]={0}; int newest[100005]={0}; stack<int> ans; void dfs(int now) { for(int next=newest[now];next<G[now].size();next=newest[now]) { newest[now]=next+1; dfs(G[now][next]); } ans.push(now); } int main() { int n,m; cin>>n>>m; for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; G[x].push_back(y); ru[y]++; } int start=1; int out=0,in=0; for(int i=1;i<=n;i++) { sort(G[i].begin(),G[i].end()); int chu=G[i].size(); if(chu-1==ru[i]) { start=i; out++; } else if(ru[i]-1==chu) { in++; } else if(chu!=ru[i]) { puts("No"); return 0; } if(in>1||out>1) { puts("No"); return 0; } } dfs(start); while(ans.size()) { cout<<ans.top()<<" "; ans.pop(); } return 0;
- 1
Information
- ID
- 1097
- Time
- 1000ms
- Memory
- 128MiB
- Difficulty
- 9
- Tags
- # Submissions
- 69
- Accepted
- 7
- Uploaded By