zoukankan      html  css  js  c++  java
  • 【拓扑排序】【CF好题】E. Directing Edges

    【拓扑排序】【好题】E. Directing Edges

    传送门

    image

    题意

    给你一些点和边,边中既有有向边和无向边,求通过对所有无向边赋予方向后,这张图是否能构成一张有向无环图(DAG)。

    思路分析

    由于没有办法更改已经形成的有向边的方向,所以如果图中的有向边已经形成了环,那么就很明确的无法构成一张DAG图了。

    而对于无向边的图我们可以把它们先看成是一个个孤立的点,又结合拓扑排序及拓扑序标记的性质,我们可以知道这些点是伙同有向边中入度为0的点在第一轮的时候就加入到队列中去。也就是它们的拓扑序肯定是小于第二轮加入的点,而我们又知道在拓扑排序中,一条有向边的起点的拓扑序是要小于这条有向边的拓扑序的。

    且若在这张图存在环,也就是说这张图中存在一些点它的入度无法通过拓扑排序的消解的过程变成0,因为只需要将拓扑排序实际处理的点数和总点数进行一个比较就可以知道这张图中是否具有环。

    #include <bits/stdc++.h>
    #define pii pair<int,int>
    #define FI first
    #define SE second
    using namespace std;
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0' && ch<='9')
            x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int N = 2E5+100,M = 2E5+100;
    struct edge{
        int u,v,ne;
    }edges[M];
    int h[N],idx;
    void add(int u,int v)
    {
    	edges[idx] = {u,v,h[u]};
    	h[u] = idx++;
    }
    int n,m;
    int indu[N],order[N],time_stamp = 0;
    void topo()
    {
    	queue<int> q;
    	for(int i=1;i<=n;i++)
    		if(!indu[i]) q.push(i);
    	
    
    	while(q.size())
    	{	
    		int u =q.front();
    		q.pop();
    		order[u] = ++time_stamp;
    		for(int i=h[u];~i;i=edges[i].ne)
    		{
    			int v = edges[i].v;
    			indu[v]--;
    			if(!indu[v])
    			   q.push(v);
    		}
    	}
    }
    vector<pii> ans;
    void init()
    {
    	ans.clear();
    	for(int i=1;i<=n;i++)
    	   h[i] = -1,order[i] = indu[i] = time_stamp = idx = 0;
    }
    int main()
    {
    	int T = read();
    	while(T--)
    	{
    		n = read(),m = read();
    		init();
    		for(int i = 1;i <= m;i++)
    		{
    			int f = read(), u = read(), v = read();
    			ans.push_back({u,v});
    			if(f) add(u,v),indu[v]++;
    		}
    	
    		topo();	
    		if(time_stamp<n)
    	       printf("NO\n");
    	    else 
        	{
    	    	printf("YES\n");
    		    for(int i=0;i<ans.size();i++)
    	        {
    		        int u = ans[i].FI, v = ans[i].SE;
    	    	    if(order[u]>order[v]) 
    		            swap(u,v);
    		        printf("%d %d\n",u,v);
    	        }
            }
    	}
        return 0;
    }
    
    
  • 相关阅读:
    Java学习--泛型
    java学习--自定义类的实例的大小比较和排序
    Java学习--枚举
    java学习--修饰符
    Java学习--变量
    POI--各种样式的XSSFCellStyle的生成
    POI 使用颜色字符串生成XSSFColor对象
    Others # 看到的一些創意 / 知乎不錯的提問/ Android安全
    RO # 不错站点
    Linux # Virtual Box VBoxGuestAdditions.iso
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15582636.html
Copyright © 2011-2022 走看看