• 【枚举】【DFS序】Gym


    题意:一颗树,每条边有个颜色,一条路径被定义为“彩虹”,当且仅当其上没有长度大于等于2的同色子路径。一个结点被定义为“超级结点”,当且仅当从其发出的所有路径都是“彩虹”。

    枚举所有长度为2,且同色的路径,其两端点方向发出的子树中的结点都不可能成为答案,只需要将它们覆盖掉即可,用dfs序处理,在左端点+1,右端点-1,最后求个前缀和,为0的结点就是没有被覆盖过的结点,也即“超级结点”。

    分两种情况:这两条边深度相同;这两条边深度不同。

    #include<cstdio>
    #include<map>
    #include<vector>
    #include<algorithm>
    using namespace std;
    int n;
    int c[50005],Map[50005];
    int fa[50005],first[50005],nex[100005],v[100005],e,Ls[50005],Rs[50005],tot,w[100005];
    int fav[50005];
    void AddEdge(int U,int V,int W){
        v[++e]=V;
        w[e]=W;
        nex[e]=first[U];
        first[U]=e;
    }
    void df1(int U){
        Ls[U]=++tot;
        Map[tot]=U;
        for(int i=first[U];i;i=nex[i]){
            if(!fa[v[i]]){
                fa[v[i]]=U;
                fav[v[i]]=w[i];
                df1(v[i]);
            }
        }
        Rs[U]=tot;
    }
    void fugai(int L,int R){
        ++c[L];
        if(R!=n){
            --c[R+1];
        }
    }
    void fugai2(int L,int R){
        if(L!=1){
            ++c[1];
            --c[L];
        }
        if(R!=n){
            ++c[R+1];
        }
    }
    void dfs(int U){
        for(int i=first[U];i;i=nex[i]){
            if(fa[v[i]]==U){
                if(U!=1 && fav[U]==w[i]){
                    fugai(Ls[v[i]],Rs[v[i]]);
                    fugai2(Ls[U],Rs[U]);
                }
                dfs(v[i]);
            }
        }
    }
    void df2(int U){
        map<int,int>cnts;
        for(int i=first[U];i;i=nex[i]){
            if(fa[v[i]]==U){
                ++cnts[w[i]];
            }
        }
        for(int i=first[U];i;i=nex[i]){
            if(fa[v[i]]==U){
                if(cnts[w[i]]>1){
                    fugai(Ls[v[i]],Rs[v[i]]);
                }
                df2(v[i]);
            }
        }
    }
    int main(){
        //freopen("g.in","r",stdin);
        scanf("%d",&n);
        int x,y,z;
        for(int i=1;i<n;++i){
            scanf("%d%d%d",&x,&y,&z);
            AddEdge(x,y,z);
            AddEdge(y,x,z);
        }
        fa[1]=-1;
        df1(1);
        dfs(1);
        df2(1);
        vector<int>vs;
        for(int i=1;i<=n;++i){
            c[i]+=c[i-1];
            //printf("%d ",c[i]);
            if(!c[i]){
                vs.push_back(Map[i]);
            }
        }
        //puts("");
        printf("%d
    ",vs.size());
        sort(vs.begin(),vs.end());
        for(vector<int>::iterator it=vs.begin();it!=vs.end();++it){
            printf("%d
    ",*it);
        }
        return 0;
    }
  • 相关阅读:
    6.基础控件
    5.对话框组合
    4.对话框程序
    3. MFC原理介绍
    三星曲面显示器
    笔记本光驱接口怎么外接台式机硬盘?
    笔记本usb外接3.5寸sata台式机硬盘, 用mhdd检测不到,怎么处理?
    MHDD检测不到硬盘的解决办法
    MHDD检测电脑硬盘坏道
    一个指向指针函数的函数指针
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7881877.html
Copyright © 2020-2023  润新知