1126 Eulerian Path(25 分)【並查集/dfs】
阿新 • • 發佈:2019-01-26
題意:如果一個連通圖的所有結點的度都是偶數,那麼它就是Eulerian,如果除了兩個結點的度是奇數其他都是偶數,那麼它就是Semi-Eulerian,否則就是Non-Eulerian
(歐拉回路:圖G的一個迴路,如果恰通過圖G的每一條邊,則該回路稱為歐拉回路,具有歐拉回路的圖稱為尤拉圖。
尤拉圖:就是從圖上的一點出發,經過所有邊且只能經過一次,最終回到起點的路徑。
尤拉通路:即可以不回到起點,但是必須經過每一條邊,且只能一次。也叫"一筆畫"問題。
判定條件(充要):
歐拉回路:1: 圖G是連通的,不能有孤立點存在。2: 對於無向圖來說度數為奇數的點個數為0;對於有向圖來說每個點的入度必須等於出度。
尤拉通路:1: 圖G是連通的,無孤立點存在。2: 對於無向圖來說,度數為奇數的的點可以有2個或者0個,並且這兩個奇點其中一個為起點另外一個為終點。對於有向圖來說,可以存在兩個點,其入度不等於出度,其中一個入度比出度大1,為路徑的起點;另外一個出度比入度大1,為路徑的終點。)
先通過並查集或dfs判斷是否為連通圖,然後判斷結點度數:
並查集:
#include <bits/stdc++.h> using namespace std; #define INF 0x7FFFFF int n,m; vector<int> g[501]; int fa[501]; int Find(int x) { if(fa[x]==x) return fa[x]; else return fa[x]=Find(fa[x]); } void Union(int x,int y) { int xc=Find(x); int yc=Find(y); if(xc!=yc) fa[xc]=yc; } int main() { while(cin>>n>>m) { int u,v; for(int i=1;i<=n;i++) //不要忘記初始化 fa[i]=i; while(m--) { cin>>u>>v; g[u].push_back(v); g[v].push_back(u); Union(u,v); } int cnt=0; for(int i=1; i<=n; i++) { if(fa[i]==i) cnt++; } int odd=0; int f=1; for(int i = 1; i <= n ; i++) { int len = g[i].size(); if(len % 2 ==1) odd++; if(f){ cout<<len; f=0; } else cout<<" "<<len; } cout<<endl; if(odd==0&&cnt==1) cout<<"Eulerian"<<endl; else if(odd==2&&cnt==1) cout<<"Semi-Eulerian"<<endl; else cout<<"Non-Eulerian"<<endl; } return 0; }
dfs:
int cnt = 0;
int vis[501];
void dfs(int index)
{
vis[index] = 1;
cnt++;
for (int i = 0; i <g[index].size(); i++)
if (vis[g[index][i]] == 0)
dfs(g[index][i]);
}
//在主函式中判斷:
cnt==n