图论-欧拉回路
欧拉回路:通过图中每条边恰好一次的回路
1:判别图中是否有欧拉回路
首先,如果一个图是欧拉图,则必须联通
检查图是否联通:
使用并查集:
有且只有一个点满足:
par[i]==i
对于无向图,记录度数d
对于有向图,记录入度,出度
u->v
出度:以u为起点
入度:以v为终点
d_out[u]++,d_in[v]++;
欧拉回路 - HDU 1878 - Virtual Judge (vjudge.net)
#include<bits/stdc++.h> const int maxn=1e3+1e1; int n,m; struct Dsu { std::array<int,maxn>par; explicit Dsu() { for(int i=0;i<maxn;i++)par[i]=i; } int find(int x) { if(par[x]==x)return x; else return par[x]=find(par[x]); } void unite(int x,int y) { x=find(x);y=find(y); if(x!=y)par[y]=x; } bool same(int x,int y){return find(x)==find(y);} }; std::array<int,maxn>degree; void solve() { Dsu dsu; int u,v; std::memset(°ree,0,sizeof(degree)); for(int i=0;i<m;i++) { std::cin>>u>>v; degree[u]++;degree[v]++; dsu.unite(u,v); } int cnt=0; bool flag=true; for(int i=1;i<=n&&flag;i++) { if(degree[i]&1)flag=false; if(dsu.par[i]==i)cnt++; if(cnt>=2){flag=false;} } if(!flag) { std::cout<<"0\n"; return; } else std::cout<<"1\n"; } int main() { while(std::cin>>n>>m&&n) { solve(); } return 0; }
Ant Trip - HDU 3018 - Virtual Judge (vjudge.net)
#include<bits/stdc++.h> const int maxn=1e5+1e1; struct Dsu { std::array<int,maxn>par; Dsu() { for(int i=0;i<maxn;i++)par[i]=i; } int find(int x) { if(x==par[x])return x; else return par[x]=find(par[x]); } void unite(int x,int y) { x=find(x),y=find(y); if(x!=y)par[y]=x; } bool same(int x,int y){return find(x)==find(y);} }; std::array<int,maxn>num,odd,d; int n,m; int main() { while(std::cin>>n>>m) { Dsu dsu; std::memset(&num,0,sizeof(num)); std::memset(&odd,0,sizeof(odd)); std::memset(&d,0,sizeof(d)); for(int i=0,u,v;i<m;i++) { std::cin>>u>>v; d[u]++;d[v]++; dsu.unite(u,v); } for(int i=1;i<=n;i++) { num[dsu.find(i)]++; if(d[i]&1)odd[dsu.find(i)]++; } int ans=0; for(int i=1;i<=n;i++) { if(num[i]<=1)continue; if(!odd[i])ans++; else ans+=odd[i]/2; } std::cout<<ans<<"\n"; } return 0; }
输出一个欧拉图的可行路径
P7771 【模板】欧拉路径 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
由于是有向图,题目也要求判断是否存在欧拉路
注意到由于题目需要字典序最小的欧拉路径
则对G[u]的所有邻接点排序
在dfs寻找欧拉路的时候,
利用当前点数组cur[u],
由于得到的欧拉路径是逆序的,逆向输出即可
在有向图判断起点,终点的时候,
出度-入度=1,的是起点,入度-出度=1的是终点
但如果都是偶点(出度==入度),任意起终点都可
#include<bits/stdc++.h> const int maxn=1e5+1e1; std::vector<int>G[maxn]; std::array<int,maxn>cur; int d[maxn][2]; int n,m; int s,t; std::vector<int>ans; void dfs(int u) { for(int v=cur[u];v<(int)G[u].size();v=cur[u]) { cur[u]=v+1; dfs(G[u][v]); } ans.emplace_back(u); } int main() { s=1; std::cin>>n>>m; int u,v; for(int i=0;i<m;i++) { std::cin>>u>>v;//u->v //出度:以u为起点 //入度:以v为终点 d[u][1]++;d[v][0]++; G[u].emplace_back(v); } for(int i=1;i<=n;i++)std::sort(G[i].begin(),G[i].end()); bool flag=true; int cnt[2]={0,0}; for(int i=1;i<=n;i++) { if(d[i][1]!=d[i][0]) { flag=false; } if(d[i][1]-d[i][0]==1) { cnt[1]++; s=i; } if(d[i][0]-d[i][1]==1) { cnt[0]++; } } if((!flag)&&!(cnt[0]==cnt[1]&&cnt[0]==1)) { std::cout<<"No\n"; return 0; } dfs(s); for(auto i=ans.rbegin();i!=ans.rend();i++) { std::cout<<*i<<" "; } std::cout<<"\n"; return 0; }
单词 Play on Words - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题就是char转换一下到int,然后有向图判定有无欧拉路径即可
#include<bits/stdc++.h> const int maxn=30; struct Dsu { std::array<int,maxn>par; Dsu() { for(int i=0;i<maxn;i++)par[i]=i; } int find(int x) { if(par[x]==x)return x; else return par[x]=find(par[x]); } void unite(int x,int y) { x=find(x),y=find(y); if(x!=y)par[y]=x; } bool same(int x,int y){return find(x)==find(y);} }; int n; std::array<std::array<int,2>,maxn>d; std::array<int,30>vis; int main() { int t;std::cin>>t; while(t--) { std::memset(&d,0,sizeof(d)); std::memset(&vis,0,sizeof(vis)); Dsu dsu; std::cin>>n; std::string s; for(int i=0;i<n;i++) { std::cin>>s; int u=*s.begin()-'a'; int v=*(s.end()-1)-'a'; if(!vis[u])vis[u]=1; if(!vis[v])vis[v]=1; dsu.unite(u,v); d[u][1]++;d[v][0]++; } int cur=0; for(int i=0;i<26;i++) { if(vis[i]) { if(dsu.par[i]==i)cur++; } } if(cur!=1) { std::cout<<"The door cannot be opened.\n"; continue; } bool flag=true; int cnt[2]={0,0}; for(int i=0;i<26;i++) { if(!vis[i])continue; if(d[i][1]!=d[i][0])flag=false; if(d[i][1]-d[i][0]==1)cnt[1]++; if(d[i][0]-d[i][1]==1)cnt[0]++; } if((!flag)&&!(cnt[0]==cnt[1]&&cnt[0]==1)) { std::cout<<"The door cannot be opened.\n"; } else std::cout<<"Ordering is possible.\n"; } return 0; }