1. 程式人生 > >判斷單向連通圖(拓撲排序+tarjan縮點)

判斷單向連通圖(拓撲排序+tarjan縮點)

empty add class () using n) 否則 memset 可能

題意: 給你一個有向圖,如果對於圖中的任意一對點u和v都有一條從u到v的路或從v到u的路,那麽就輸出’Yes’,否則輸出’No’.

理解:當出現兩個及以上入度為0的點(有一個就可能是別人到它,有兩個的話那麽那兩個就互相到不了,因為他們入度都為0),就必定有不滿足連通性的,但是如果只是單純判斷出度入度,會將重邊誤算,所以應該要用拓撲排序。拓撲排序之前,應該先進行縮點。

註意:多組數據,要記得清0!!

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
const
int M=N*N; int to[M],t[M],head[N],hea[N],nex[M],ne[M],tot,tott; int cnt,T,stk[N],flag[N],low[N],vis[N],top,bel[N]; queue<int >q; int in[N]; void add1(int a,int b) { to[++tot]=b; nex[tot]=head[a]; head[a]=tot; } void add2(int a,int b) { t[++tott]=b; ne[tott]=hea[a]; hea[a]=tott; }
void init() { top=0,tot=0,tott=0,cnt=0,T=0; memset(to,0,sizeof(to));memset(t,0,sizeof(t)); memset(head,0,sizeof(head));memset(hea,0,sizeof(hea)); memset(nex,0,sizeof(nex));memset(ne,0,sizeof(ne)); memset(vis,0,sizeof(vis));memset(low,0,sizeof(low)); memset(stk,0,sizeof(stk));memset(in
,0,sizeof(in)); memset(flag,0,sizeof(flag)); while(!q.empty()) q.pop(); } void tarjan(int x) { vis[x]=low[x]=++T; stk[++top]=x; flag[x]=1; for(int i=head[x];i;i=nex[i]) { int v=to[i]; if(!vis[v]) { tarjan(v); low[x]=min(low[x],low[v]); } else if(flag[v]) low[x]=min(low[x],vis[v]); } if(vis[x]==low[x]) { cnt++; do{ flag[stk[top]]=0; bel[stk[top]]=cnt; }while(stk[top--]!=x); } } void build(int u) { for(int i=head[u];i;i=nex[i]) if(bel[u]!=bel[to[i]]) add2(bel[u],bel[to[i]]),in[bel[to[i]]]++;//bel[to[i]]!! } bool topo() { //printf("%d\n",cnt); for(int i=1;i<=cnt;i++) if(!in[i]) q.push(i); while(!q.empty()) { if(q.size()>1) return false; int u=q.front(); q.pop(); for(int i=hea[u];i;i=ne[i]) { int v=t[i]; in[v]--; if(!in[v]) q.push(v); } } return true; } int main() { freopen("graph.in","r",stdin); freopen("graph.out","w",stdout); int n,m,Ti,a,b; scanf("%d",&Ti); while(Ti--) { init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d",&a,&b),add1(a,b); for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i); for(int i=1;i<=n;i++) build(i); if(!topo()) printf("No\n"); else printf("Yes\n"); } } /* 2 3 2 1 3 2 3 3 2 1 2 2 3 */

判斷單向連通圖(拓撲排序+tarjan縮點)