poj 2762 强连通缩点+拓扑排序
这题搞了好久,先是拓扑排序这里没想到,一开始自己傻乎乎的跑去找每层出度为1的点,然后才想到能用拓扑排序来弄。
拓扑排序的时候也弄了挺久的,拓扑排序用的也不多。
题意:给一个图求是否从对于任意两个点能从v 到w 或者从w到v连通。
思路:单连通,先强连通缩点,若scnt为1,或者出度为零的点为0,直接输出YES,若出度为零的点大于1,则代表有分支输出NO。若出度为零的点为1,判断组成的树是否为单链,即没有分支,用拓扑排序即可。
代码:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define MAXN 1100 #define MAXM 6600 struct Edge { int to,next; }edge[MAXM]; int first[MAXN], stack[MAXN], DFN[MAXN], Low[MAXN], Belong[MAXN]; int indegree[MAXN],instack[MAXN]; int n,m,tot,scnt,top,cnt; bool new_map[MAXN][MAXN];int vis[MAXN]; void Tarjan(int v) { int min,t; DFN[v]=Low[v]=++tot; instack[v]=1; stack[top++]=v; for(int e=first[v];e!=-1;e=edge[e].next) { int j=edge[e].to; if(!DFN[j]) { Tarjan(j); if(Low[v]>Low[j])Low[v]=Low[j]; } else if(instack[j]&&DFN[j]<Low[v]) { Low[v]=DFN[j]; } } if(DFN[v]==Low[v]) { scnt++; do { t=stack[--top]; instack[t]=0; Belong[t]=scnt; }while(t!=v); } } void read_graph(int v,int w) { edge[tot].to=w; edge[tot].next=first[v]; first[v]=tot++; } void solve() { for(int i=1;i<=n;i++) if(!DFN[i]) Tarjan(i); } void process(int j,int n) { for(int i=1;i!=n+1;i++) { if(new_map[j][i]) indegree[i]--; } } int check(int n) { int count(0); int t(0); for(int i=1;i!=n+1;i++) { if(vis[i]==false&&indegree[i]==0) { t=i; vis[i] = true; count++; } } if(t!=0) process(t,n); return count; } bool topo_sort(int n) { memset(vis,false,sizeof(vis)); for(int i=1;i!=n+1;i++) { if(check(n)>1) return false; } return true; } int main() { int T; scanf("%d",&T); while(T--) { memset(indegree,0,sizeof(indegree)); memset(DFN,0,sizeof(DFN)); memset(first,-1,sizeof(first)); cnt=scnt=tot=top=0; memset(new_map,false,sizeof(new_map)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int v,w; scanf("%d%d",&v,&w); read_graph(v,w); } solve(); //cout<<scnt<<endl; if(scnt==1) { printf("Yes\n"); continue; } for(int i=1;i<=n;i++) { for(int j=first[i];j!=-1;j=edge[j].next) { int v=edge[j].to; if(Belong[i]!=Belong[v]) { new_map[Belong[i]][Belong[v]] = true; indegree[Belong[v]]++; } } } int count1=0; for(int i=1;i<=scnt;i++) { if(indegree[i]==0) count1++; } if(count1==0) { printf("Yes\n"); continue; } else if(count1>1) { printf("No\n"); continue; } if(topo_sort(scnt)) printf("Yes\n"); else printf("No\n"); } return 0; }