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
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14062718.html