• AT2377 [AGC014E] Blue and Red Tree


    Description

    $ N $ 頂点からなる木があり、頂点には $ 1 $ から $ N $ の番号がついています。 また、 $ N-1 $ 本の辺の内、 $ i $ 番目の辺は頂点 $ a_i $ と頂点 $ b_i $ を結んでいます。

    はじめ、各辺は青色に塗られています。 そこで、高橋君は以下の操作を $ N-1 $ 回行い、赤色の木に作り替えることにしました。

    - 青色の辺のみからなるパスを一つ選び、そのパス上の辺を一つ取り除く。
    - その後、初めに選んだパスの両端点間に赤色の辺を追加する。

    最終的に、各 $ i $ に対し、頂点 $ c_i $ と頂点 $ d_i $ を結ぶ赤い辺が存在するような $ N $ 頂点の木に作り替えたいです。

    これが可能であるかどうか判定してください。

    Solution

    新树的每条边在原树上覆盖,最后一次替换的一定是覆盖次数为1的,之前几次以此类推

    发现最后一次替换一定是新树上有的边,于是用set保存边集信息,在原树上做dsu on tree

    维护边集信息和一个并查集

    如果能将所有的点都缩起来说明可行

    #include<iostream>
    #include<utility>
    #include<cstdio>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    int n,fa[100005],ans;
    queue<pair<int,int> >q;
    set<int>s[100005];
    map<pair<int,int>,int>mp;
    inline int read()
    {
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return f*w;
    }
    int find(int x)
    {
        return (fa[x]==x)?fa[x]:fa[x]=find(fa[x]);
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            s[u].insert(v),s[v].insert(u);
            mp[make_pair(u,v)]++,mp[make_pair(v,u)]++;
        }
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            s[u].insert(v),s[v].insert(u);
            mp[make_pair(u,v)]++,mp[make_pair(v,u)]++;
            if(mp[make_pair(u,v)]==2) q.push(make_pair(u,v));
        }
        while(q.size())
        {
            int u=find(q.front().first),v=find(q.front().second);
            q.pop();
            s[u].erase(v),s[v].erase(u);
            if(s[u].size()>s[v].size()) swap(u,v);
            for(set<int>::iterator it=s[u].begin();it!=s[u].end();it++)
            {
                mp[make_pair(u,*it)]=mp[make_pair(*it,u)]=0;
                mp[make_pair(v,*it)]++,mp[make_pair(*it,v)]++;
                if(mp[make_pair(v,*it)]==2) q.push(make_pair(v,*it));
                s[v].insert(*it),s[*it].insert(v),s[*it].erase(u);
            }
            s[u].clear(),fa[u]=v;
        }
        for(int i=1;i<=n;i++) if(fa[i]==i) ++ans;
        if(ans==1) puts("YES");
        else puts("NO");
        return 0;
    }
    Blue and Red Tree
  • 相关阅读:
    WPF中更改键盘默认指令小结
    WPF自己喜欢用的数据验证方式
    重写Windows基类,自定义WPF窗口,实现改回车键为TAB
    用CSS控制表格的框格线
    获取当前鼠标的坐标
    SQL 中的转义字符
    資料站點
    jquery 弹出浮层(div) + 遮蔽层
    Jquery放大镜插件[JMagazine]使用参数简介
    邏輯題 交通事故篇
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14062718.html
Copyright © 2020-2023  润新知