POJ2762 Going from u to v or from v to u(单连通 缩点)

判断图是否单连通,先用强连通分图处理,再拓扑排序,需注意:

 

符合要求的不一定是链
拓扑排序列结果唯一,即在队列中的元素始终只有一个

 

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
#include<stack>
using namespace std;
typedef long long LL;
const int N = 1008, INF = 0x3F3F3F3F;
int dfn[N],id[N];
int lab,cnt;
stack <int> st;
int n, m;
int head[N], tot;
int indeg[N];
vector<int> g[N];
void init(){
	memset(head, - 1,sizeof(head));
	tot=  0;
}

struct Edge{
	int to, next;
}edge[20008];

void add(int u, int v){
	edge[tot].to = v;
	edge[tot].next = head[u];
	head[u] = tot++;
}

int dfs(int u){
	int lowu=dfn[u]=++lab;
	st.push(u);
    for(int i = head[u];i!=-1;i=edge[i].next){
        int v = edge[i].to;
        if(!dfn[v]){
            int lowv = dfs(v);
            lowu = min(lowu, lowv);
        }else if(!id[v]) {
            lowu = min(lowu, dfn[v]);
        }
    }
    if(lowu == dfn[u]){
        cnt++;
        while(1){
            int x = st.top();
            st.pop();
            id[x] = cnt;
            if(x == u) break;
        }
    }
    return lowu;
}
int tarjan(){
    for(int i=1;i<=n;i++) {
        dfn[i] = id[i] = 0;
    }
    lab=cnt=0;
    for(int i=1;i<=n;i++) {
        if(!dfn[i]){
         dfs(i);
        }
    }
    return cnt;
}

//符合要求的不一定是链
//拓扑排序列结果唯一,即在队列中的元素始终只有一个
bool topsort(int n){
    queue<int > q;
    int sum = 0;
    for(int i = 1; i <= n; i++){
        if(indeg[i] == 0){
            q.push(i);
            if(q.size() > 1){
               return false;
            }
        }
    }
    while(!q.empty()){
        int u = q.front();
        q.pop();
        sum++;
        for(int i= 0; i < g[u].size(); i++){
        	int v = g[u][i];
        	indeg[v]--;
        	if(indeg[v] == 0){
        		q.push(v);
        	}
        }
        if(q.size() > 1){
        	return false;
        }
    }
    if(sum != n){
        return false;
    }
    return true;
}
int main(){
    int t;
    cin>>t;
    while(t--){
    	init();
    	memset(indeg, 0, sizeof(indeg));
    	scanf("%d %d", &n, &m);
    	while(m--){
    		int u, v;
    		scanf("%d %d", &u, &v);
    		add(u, v);
    	}
    	tarjan();
    	for(int i =1; i<= cnt; i++){
            g[i].clear();
    	}
    	for(int u = 1; u <= n; u++){
    		for(int i = head[u] ; ~i ; i = edge[i].next){
    			int v = edge[i].to;
    			if(id[u] != id[v]){
    				indeg[id[v]]++;
    				g[id[u]].push_back(id[v]);
    			}
    		}
    	}
    	if(topsort(cnt)){
            printf("Yes\n");
    	}else{
    		printf("No\n");
    	}
    }
    return 0;
}

  

posted @ 2016-08-10 10:20  vwirtveurit  阅读(160)  评论(0编辑  收藏  举报