• Going from u to v or from v to u?_POJ2762强连通+并查集缩点+拓扑排序


         Going from u to v or from v to u?
    Time Limit: 2000MS   Memory Limit: 65536K
         

    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

    POJ Monthly--2006.02.26,zgl & twb


    题意:jiajia有一个洞穴,洞穴中有n个房间,房间的连接是有方向的,jiajia想知道u与v之间是不是有路径u->v或v->u


    思路:单连通问题,首先将图中的强连通的部分进行缩点,构成一颗树,接下来拓扑排序,判断拓扑排序的两点之间是不是有边,如果没有边则图不符合要求。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <algorithm>
    
    using namespace std;
    
    const int Max = 1100;
    
    const int INF = 0x3f3f3f3f;
    
    typedef struct node
    {
    	int v;
    	
    	int next;
    
    }Line ; 
    
    
    Line Li[Max*6];
    
    int Head[Max],top;
    
    int Map[Max][Max];
    
    int Du[Max],pre[Max];
    
    int vis1[Max],dfn[Max],low[Max];
    
    bool vis2[Max];
    
    int dep;
    
    int Point[Max*5][2],Num;
    
    int topo[Max],num;
    
    int a[Max],ToNum;
    
    stack < int >S;
    
    void AddEdge(int u,int v)
    {
    	Li[top].v = v; Li[top].next = Head[u];
    
    	Head[u] = top++;
    }
    
    
    int Find(int x)
    {
    	return pre[x]==-1?x:pre[x] = Find(pre[x]);
    }
    
    void Tarjan(int u) //强连通缩点
    {
    
    	dfn[u] = low[u] = dep++;
    
    	vis1[u] = 1;
    
    	S.push(u);
    
    	for(int i=Head[u];i!=-1;i=Li[i].next)
    	{
    		if(vis1[Li[i].v]==1)
    		{
    			low[u]=min(low[u],dfn[Li[i].v]);
    		}
    		if(vis1[Li[i].v]==0)
    		{
    			Tarjan(Li[i].v);
    
    			low[u]=min(low[u],low[Li[i].v]);
    		}
    
    		if(vis2[Li[i].v])
    		{
    			Point[Num][0]=u;
    
    			Point[Num++][1]=Li[i].v;
    		}
    	}
    
    	if(low[u]==dfn[u]) //如果low[u]==dfn[u],则说明是强连通的根节点。
    	{
    		vis2[u]=true;
    
    		topo[num++] = u;
    
    		while(1)
    		{
    			if(S.empty())
    			{
    				break;
    			}
    			int v = S.top();
    
    			S.pop();
    
    			vis1[v]=2;
    
    			if(v==u)
    			{
    				break;
    			}
    			pre[v]=u;
    
    		}
    	}
    }
    
    void Toposort()//BFS拓扑排序
    {
    
    	queue<int>Q;
    	for(int i=0;i<num;i++)
    	{
    		if(Du[topo[i]]==0)
    		{
    			Q.push(topo[i]);
    
    		}
    	}
    	while(!Q.empty())
    	{
    		int u=Q.front();
    
    		a[ToNum++]=u;
    
    		Q.pop();
    
    		for(int i=0;i<num;i++)
    		{
    			if(Map[u][topo[i]])
    			{
    				Du[topo[i]]--;
    
    				if(Du[topo[i]]==0)
    				{
    					Q.push(topo[i]);
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    
    	int T;
    
    	int n,m;
    
    	scanf("%d",&T);
    
    	while(T--)
    	{
    		scanf("%d %d",&n,&m);
    
    		top =  0;
    
    		memset(Head,-1,sizeof(Head));
    
    		int u,v;
    
    		for(int i=0;i<m;i++)
    		{
    			scanf("%d %d",&u,&v);
    
    			AddEdge(u,v);
    		}
    
    		memset(vis1,0,sizeof(vis1));
    
    		memset(Map,0,sizeof(Map));
    
    		memset(vis2,false,sizeof(vis2));
    
    		memset(Du,0,sizeof(Du));
    
    		memset(pre,-1,sizeof(pre));
    
    		dep  = 0; Num  =0 ;num = 0;
    
    		while(!S.empty())
    		{
    			S.pop();
    		}
    
    		for(int i=1;i<=n;i++)
    		{
    			if(vis1[i]==0)
    			{
    				Tarjan(i);
    			}
    		}
    		for(int i=0;i<Num;i++)
    		{
    
    			int x = Find(Point[i][0]);
    
    			int y = Find(Point[i][1]);
    
    			Map[x][y]=1;
    
    			Du[y]++;
    		}
    
    		ToNum = 0;
    
    		Toposort();
    
    		bool flag=false;
    
    		for(int i=0;i<ToNum-1;i++)
    		{
    			if(!Map[a[i]][a[i+1]])//判断相邻的是不是存在边
    			{
    				flag=true;
    
    				break;
    			}
    		}
    
    		if(flag)
    		{
    			printf("No
    ");
    		}
    		else
    		{
    			printf("Yes
    ");
    		}
    
    	}
    
    	return 0;
    }
    


  • 相关阅读:
    又来项目了,星座运势widget
    ubuntu下编译android源代码
    Android UI,界面辅助设置工具,可随意拖动控件,比google官方提供的方便
    Android 1.5原生软件开发SDK公布
    REST转自WIKI
    Android SDK 1.5 包装索引
    android google market FreshFace上线了,大家都试用试用,反正免费的
    JSON
    ubuntu命令
    网站支付宝接口错误代码:TRADE_DATA_MATCH_ERROR怎么处理? uz
  • 原文地址:https://www.cnblogs.com/juechen/p/5255891.html
Copyright © 2020-2023  润新知