• codeforces 1217D Coloring Edges 题解


    挺有意思的一道题。

    首先如果没有环,那么一种颜色染完所有边,答案为 (1)
    这里我直接用拓扑排序判断有没有环了。

    如果有环,一种颜色肯定是不行了。我们发现对于每一个环,可以视为从一个点出发,经过另一些点,再回到这个点的路径。
    这里我们给每一个点任意赋予一个高度(就是赋予一个权值..吧),同时保证所有点高度不同,这时候我们发现从一个点 (x) 出发,走完第一步之后,要么是到达了高度比原来更高的点,要么到达了高度比原来更低的点,而最后我们要回到 (x),如果第一步往高处走了,环上总有至少一步需要往低处走,不然一定无法回到 (x)。另一种情况同理。

    总而言之,每一个环必定同时包含走向更高高度的边和走向更低高度的边。

    所以把高往低走的边染色为 (1),低往高走的染色为 (2)

    然后这题就做完了。

    高度怎么赋?随便怎么搞都可以,只要两两不同就行了。
    这里我为了方便直接用了点的编号

    代码:

    // 头文件省略了
    using namespace std;
    typedef long long LL;
    
    vector <LL> G[200005];
    LL vis[200005],in[200005] = {0};
    LL cnt = 0,n,m;
    
    void tp_sort(){
    	queue <LL> q;
    	for(LL i = 1;i <= n;i ++){
    		if(!in[i]){
    			cnt --;
    			q.push(i);
    		}
    	}
    	while(!q.empty()){
    		LL u = q.front(); q.pop();
    		for(LL i = 0;i < G[u].size();i ++){
    			LL v = G[u][i]; in[v] --;
    			if(!in[v]){
    				cnt --;
    				q.push(v);
    			}
    		}
    	}
    } // 拓扑排序
    
    LL u[200005],v[200005],col[200005];
    
    int main(){
    	cin >> n >> m;
    	for(LL i = 1;i <= m;i ++){
    		cin >> u[i] >> v[i];
    		G[u[i]].push_back(v[i]); in[v[i]] ++;
    	}
    	cnt = n; tp_sort();
    	if(!cnt){
    		cout << 1 << endl;
    		for(LL i = 1;i <= m;i ++) cout << 1 << (i == m ? '
    ' : ' ');
    		return 0; // 判断无环的情况
    	}
    	
    	for(LL i = 1;i <= m;i ++){
    		if(v[i] < u[i]) col[i] = 2;
    		if(v[i] > u[i]) col[i] = 1;
    	} // 有环,直接根据点编号大小关系给边染色
    	cout << 2 << endl;
    	for(LL i = 1;i <= m;i ++) cout << col[i] << (i == m ? '
    ' : ' ');
    	return 0;
    }
    //
    
  • 相关阅读:
    认识Linux
    Java之安装环境
    Markdown学习
    使用cacti监控linux server的接口流量
    IDRAC安装dell服务器操作系统(linux or windows),用到生命周期管理器
    网络编程--练习题
    linux搭建ntp服务器-添加交换机客户端,windows客户端
    linux centos7搭建redis-5.0.5
    linux centos7搭建mysql-5.7.29
    对称加密与非对称加密
  • 原文地址:https://www.cnblogs.com/IltzInstallBI/p/12744267.html
Copyright © 2020-2023  润新知