• POJ 2762推断单个联通(支撑点甚至通缩+拓扑排序)


    Going from u to v or from v to u?
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 14789   Accepted: 3915

    Description

    In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?

    Input

    The first line contains a single integer T, the number of test cases. And followed T cases. 

    The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly. 

    Output

    The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.

    Sample Input

    1
    3 3
    1 2
    2 3
    3 1
    

    Sample Output

    Yes

    Source

    [Submit]   [Go Back]   [Status]   [Discuss]


    题意:对于随意两个节点u,v。假设能从u到v或者v到u,那么输出Yes,否则输出No。

    思路:先强连通缩点,此时一定不含环,看能不能找到一条最长路包括全部的缩点即可(实际上是找推断单链),用拓扑排序就ok,只是假设仅仅有一个强连通分量那么一定是Yes啦,否则topo排序推断 ,代码例如以下

    #include<iostream>  
    #include<algorithm>  
    #include<cstdio>  
    #include<queue>
    #include<cstring>  
    #include<cmath>  
    using namespace std;
    typedef long long ll;
    const int maxn =1e4+10;
    const ll mod=20140413;
    vector<int>G1[maxn],G2[maxn],G[maxn];
    int sccno[maxn],vis[maxn],scc_cnt;//sccno强连通编号,scc_cnt表示强连通分量的个数
    int ind[maxn];//ind表示入度
    void init_G(int n)//初始化缩点图
    {
    	memset(ind,0,sizeof ind);
    	for(int i=1;i<=n;i++)G[sccno[i]].clear();
    	for(int i=1;i<=n;i++) {
    		for(int j=0;j<G1[i].size();++j){
    			int &v =G1[i][j];
    			if(sccno[i]!=sccno[v]) {
    				G[sccno[i]].push_back(sccno[v]);
    				ind[sccno[v]]++;
    			}
    		}
    	}
    }
    bool toposort(int n)//topo排序
    {
    	init_G(n);
    	int u,cnt=0;
    	queue<int>q;
    	for(int i=1;i<=n;i++){
    		if(!ind[sccno[i]]){
    			if(!q.empty())return false;
    			q.push(sccno[i]);
    			cnt++;
    		}
    	}
    	while(!q.empty()){
    		u=q.front();
    		q.pop();
    		ind[u]=-1;
    		for(int i=0;i<G[u].size();i++) {
    			int &v=G[u][i];
    			ind[v]--;
    			if(ind[v]==0){
    				if(!q.empty())return false;
    				q.push(v);
    				cnt++;
    			}
    		}
    	}
    	return cnt==scc_cnt;
    }
    vector<int>S;
    void init(int n)
    {
    	memset(vis,0,sizeof vis);
    	memset(sccno,0,sizeof sccno);
    	S.clear();
    	scc_cnt=0;
    	for(int i=1;i<=n;i++) {
    		G1[i].clear();
    		G2[i].clear();
    		G[i].clear();
    	}
    }
    void AddEdge(int u,int v)
    {
    	G1[u].push_back(v);
    	G2[v].push_back(u);
    }
    void dfs1(int u)
    {
    	if(vis[u])return ;
    	vis[u]=1;
    	for(int i=0;i<G1[u].size();i++)dfs1(G1[u][i]);
    	S.push_back(u);
    }
    void dfs2(int u)
    {
    	if(sccno[u]) return ; 
    	sccno[u]=scc_cnt;
    	for(int i=0;i<G2[u].size();++i)dfs2(G2[u][i]);
    }
    bool is_Semiconnect(int n)///计算强连通分量,初步推断
    {
    	for(int i=1;i<=n;i++)dfs1(i);
    	for(int i=S.size();i>=1;i--){
    		if(!sccno[S[i-1]]){
    			scc_cnt++;
    			dfs2(S[i-1]);
    		}
    	}
    	return scc_cnt<=1;
    }
    int main()  
    {  
       int T,n,m; 
       scanf("%d",&T);
       while(T--) {
       		scanf("%d%d",&n,&m);
       		int u,v;
       		init(n);
       		while(m--) {
       			scanf("%d%d",&u,&v);
       			AddEdge(u,v);
       		}
       		if(is_Semiconnect(n))puts("Yes");
       		else{
       			if(toposort(n))puts("Yes");
       			else puts("No");
       		}
       	}
       return 0;  
    }

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    Thinkphp 边学边用验证码无意间犯的错
    如何计算团队成员贡献分
    禅道使用之项目经理篇
    禅道使用之开发团队篇
    黑盒测试实践作业进度报告(周日)
    黑盒测试实践作业进度报告(周六)
    禅道使用之产品经理篇
    第1周小组博客作业——关于禅道测试管理的总结
    禅道介绍与环境搭建
    一个工作了5年的程序员,将来在哪里?
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4728238.html
Copyright © 2020-2023  润新知