zoukankan      html  css  js  c++  java
  • Codeforces 1217D Coloring edges

    题目链接:https://www.luogu.org/problem/CF1217D

    题意:请给一个有向图着色,使得没有一个环只有一个颜色,您需要最小化使用颜色的数量。

    分析:无环的时候显然答案就是1

    而有环答案是2

    证明: 首先我们可以考虑dfs树,在有向图中,只存在三种边,返祖边,树边,横叉边, 然而横叉边在有向图中并不能构成一个环,所以在有向图中,一个环必然同时包含返祖边和树边两种边,那么我们只需要将所有的返祖边染成1,树边染成2,那么一个换中就肯定不止一种颜色了。

    相关知识:图的遍历中,往往设置了一个标记数组vis的bool值来记录顶点是否被访问过。但有些时候需要改变vis值的意义。令vis具有3种值并表示3种不同含义
    vis = 0,表示该顶点没没有被访问
    vis = 1,表示该顶点已经被访问,但其子孙后代还没被访问完,也就没从该点返回
    vis = 2,,表示该顶点已经被访问,其子孙后代也已经访问完,也已经从该顶点返回,注意没返回是不算的,这里可以假设这个定点还有个null孩子,还没访问这个null孩子就不算已经访问完

    DFS过程中,对于一条边u->v
    vis[v] = 0,说明v还没被访问,v是首次被发现,u->v是一条树边,真正的dfs路径中的边
    vis[v] = 1,说明v已经被访问,但其子孙后代还没有被访问完(正在访问中),而u又指向v?说明u就是v的子孙后代,u->v是一条后向边,因此后向边又称返祖边,有环的时候回去的边,因此判断有没有环可以判断有没有后向边就可以了。
    vis[v] = 2,z说明v已经被访问,其子孙后代也已经全部访问完,u->v这条边可能是一条横叉边,或者前向边,比如跨树的时候其实就是横叉变,就是一棵树访问完了访问下一棵树了该。而前向边可以理解为就是父亲指向孩子,但是已经访问过了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=5010;
    const int N=1e3+7;
    const int inf=0x3f3f3f3f;
    int head[maxn];
    int nxt[maxn];
    int to[maxn];
    int vis[maxn];
    int cnt;
    int ans[maxn];
    bool cyc;
    void add(int u,int v){
        cnt++;
        to[cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void dfs(int u){
        vis[u]=1;//点u已经被访问了但其子孙后代还没被访问完。 
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(vis[v]==0){//这是条树边 
                dfs(v);
                ans[i]=1;
            }
            else if(vis[v]==2)//横断边 
                ans[i]=1;
            else if(vis[v]==1)//返祖边 
                cyc=1,ans[i]=2;
        }
        vis[u]=2;//点u已经被访问了 
    }
    int main(){
        int n,m;scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v;scanf("%d%d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++){
            if(!vis[i])
                dfs(i);
        }
        if(cyc)printf("2
    ");
        else printf("1
    ");
        for(int i=1;i<m;i++)printf("%d ",ans[i]);
        printf("%d
    ",ans[m]);
        return 0;
    }
  • 相关阅读:
    js表单验证
    i利用图片按钮 和 input type="image" 为背景提交表单
    php 时间转换
    select 响应时间 js
    浏览器兼容
    选修课程的级联。
    时间显示的位置
    广告飘动
    C++--引用
    ubuntu中可以ping通IP地址但是ping不通域名的问题(www.baidu.com)
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11556914.html
Copyright © 2011-2022 走看看