1. 程式人生 > >HDU-5215 Cycle 無向圖判奇環偶環

HDU-5215 Cycle 無向圖判奇環偶環

include bit 題意 但是 二分圖染色 while names can esp

題意:給一個無向圖,判斷這個圖是否存在奇環和偶環。

解法:網上有一種只用dfs就能做的解法,但是我不太理解。

這裏用的是比較復雜的。首先奇環很簡單可以用二分圖染色判斷。問題是偶環怎麽判斷?這裏我們想,一旦有兩個環共享了一些點,那麽這兩個環一定能組成一個偶環。

那麽我們考慮tarjan找出所有橋刪去,那麽對於一個邊雙聯通分量,這個邊雙只要有多於一個環就必定存在偶環。即當且僅當這個邊雙為一個奇環的情況下才不存在偶環,其他情況都會有偶環。

所以一旦這個邊雙不是單環,就必定存在偶環。

那麽怎麽判斷這個是不是一單個環呢?點數=邊數的時候就是一個單環。

細節詳見代碼:

#pragma comment(linker,"/STACK:102400000,102400000")
#include
<bits/stdc++.h> using namespace std; const int N=3e5+10; int n,m,ver,edge,odd,even,col[N]; bool bridge[N]; int cnt=1,head[N<<1],nxt[N<<1],to[N<<1]; void add_edge(int x,int y) { nxt[++cnt]=head[x]; to[cnt]=y; head[x]=cnt; } int num,low[N],dfn[N]; void tarjan(int
x,int in) { dfn[x]=low[x]=++num; for (int i=head[x];i;i=nxt[i]) { int y=to[i]; if (!dfn[y]) { tarjan(y,i); low[x]=min(low[x],low[y]); if (low[y]>dfn[x]) bridge[i]=bridge[i^1]=1; } else if (i!=(in
^1)) low[x]=min(low[x],dfn[y]); } } void dfs(int x,int fa) { col[x]=3-col[fa]; ver++; for (int i=head[x];i;i=nxt[i]) { if (bridge[i]) continue; int y=to[i]; edge++; if (y==fa) continue; if (!col[y]) dfs(y,x); else if (col[x]==col[y]) odd=1; else even=1; //染色過程判斷奇偶環 } } int main() { int T; cin>>T; while (T--) { cin>>n>>m; cnt=1; for (int i=1;i<=n;i++) head[i]=0; for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); add_edge(x,y); add_edge(y,x); } num=0; for (int i=1;i<=n;i++) dfn[i]=low[i]=0; for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,0); //找橋 odd=even=0; for (int i=1;i<=n;i++) col[i]=0; col[0]=1; for (int i=1;i<=n;i++) if (!col[i]) { ver=0; edge=0; dfs(i,0); if (ver>1 && edge/2!=ver) even=1; //點數和邊數不等,存在偶環 } printf("%s\n",odd?"YES":"NO"); printf("%s\n",even?"YES":"NO"); for (int i=0;i<=cnt;i++) bridge[i]=0; } return 0; }

HDU-5215 Cycle 無向圖判奇環偶環