AtCoder Grand Contest 014 E:Blue and Red Tree

题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_e

题目翻译

有一棵有\(N\)个点的树,初始时每条边都是蓝色的,每次你可以选择一条由蓝色边构成的简单路径,让这条路径的两个端点间连上一条红边,然后断开这条路径上的某条蓝边。这样做\(N-1\)次,就可以把原本的蓝树变成红树。现在给你蓝树和红树的样子,问你可不可能把给出的蓝树变成给出的红树。\(N\leqslant 10^5\)

题解

先膜一发大佬的题解:https://blog.csdn.net/sadnohappy/article/details/79478193

也许是昨天状态不好……想了一下午都想不出……就去看题解了……

思路想到一半卡住了,看了题解的最后一步思路之后不知道怎么实现,我觉得我还是太菜了。

先讲讲我一个\(O(N^2logn)\)的暴力吧:

因为每次连红边都要保证两点之间有一条完全由蓝边构成的简单路径,然后断开某条蓝边。所以我们把所有路径都丢到树上去差分一下,然后求出每条边被多少条路径覆盖,每次把只被覆盖一次的蓝边断开,然后把那一条唯一的覆盖它的红边的差分影响消去,更新一下差分值。这样子如果做不了\(N-1\)次就是\(NO\),否则\(YES\)。

顺着这个思路往下想,既然我可以知道顺着怎么一条一条边断开,我当然也可以知道逆着怎么一条一条边接上来。然后我自己就想不出接下来该怎么办了。

因为最后一条断开的边肯定是红蓝都一样的,那么我假设这个蓝边一开始就不存在,然后把这条蓝边链接的两个点合成一个点,把所有边的信息都更新一下,我们会发现接下来删的蓝边应该也会存在一条红边对应。这样做\(N-1\)次就行了。因为我是倒着做的,所以之前被我印点的断开的边在现在被我选中的路径上还是连上的。

至于实现,看代码吧……我基本不用\(stl\)的……但是我真的不知道还有什么别的实现方法……

时间复杂度:\(O(NlogN)\)

空间复杂度:\(O(N)xinxi\)

代码如下:

#include <set>
#include <map>
#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;

const int maxn=1e5+5;

int n;
int fa[maxn];
queue<pii> q;
set<int>s[maxn];
map<pii,int>cnt;
set<int>::iterator it;

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

int find(int x) {
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);
}

int main() {
    n=read();
    for(int i=1;i<2*n-1;i++) {
        int x=read(),y=read();
        s[x].insert(y),s[y].insert(x);
        if(x>y)swap(x,y);
        pii tmp=make_pair(x,y);
        cnt[tmp]++;
        if(cnt[tmp]==2)q.push(tmp);
    }
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<n;i++) {
        if(q.empty()) {puts("NO");return 0;}
        int x=0,y=0;
        for(;x==y;x=find(q.front().first),y=find(q.front().second),q.pop());
        if(s[x].size()>s[y].size())swap(x,y);fa[x]=y;//启发式合并,保证每条边最多被合并logn次
        for(it=s[x].begin();it!=s[x].end();it++) {
            int v=*s[x].find(*it);
            s[v].erase(s[v].find(x));
            if(v==y)continue;
            s[v].insert(y),s[y].insert(v);
            pii tmp;
            if(v>y)tmp=make_pair(y,v);
            else tmp=make_pair(v,y);
            cnt[tmp]++;
            if(cnt[tmp]==2)q.push(tmp);
        }//更新边的信息
    }
    puts("YES");
    return 0;
}

原文地址:https://www.cnblogs.com/AKMer/p/10030259.html

时间: 2024-07-30 15:38:04

AtCoder Grand Contest 014 E:Blue and Red Tree的相关文章

AtCoder Grand Contest 014

AtCoder Grand Contest 014 A - Cookie Exchanges 有三个人,分别有\(A,B,C\)块饼干,每次每个人都会把自己的饼干分成相等的两份然后给其他两个人.当其中有一个人的饼干数量是奇数的时候停止,求会进行几次这样子的操作,或者会永远进行下去. 首先无解的情况一定是三个数都是相等的偶数. 否则直接暴力模拟就行了.(盲猜答案不会很大) 证明一下答案的范围:不妨令\(A\le B\le C\),那么最大值和最小值之间的差就是\(C-A\),那么执行完一次操作之后

AtCoder Grand Contest 012 C:Tautonym Puzzle

题目传送门:https://agc012.contest.atcoder.jp/tasks/agc012_c 题目翻译 如果一个字符串是好的,那么这个字符串的前半部分和后半部分肯定一模一样.比如\(aa\)与\(bubobubo\)就是好的串,而空串,\(a\)与\(abcabcabc\)以及\(abba\)就不是好的.现在给你一个小于等于\(10^{12}\)的数字\(N\),要你求出一个字符串\(s\),使得这个串的\(2^{len}-1\)个子串里刚好有\(N\)个子串是好的.要求\(le

AtCoder Grand Contest 028 A:Two Abbreviations

题目传送门:https://agc028.contest.atcoder.jp/tasks/agc028_a 题目翻译 给你两个串\(s\)与\(t\),长度分别为\(n,m\).问你存不存在一个串长度为\(l\),\(l\)是\(n,m\)的公倍数,并且满足下面的条件: \(1\).对于第\(1\)位.第\(l/n+1\)位,第\(2*l/n+1\)位--第\((n-1)*l/n+1\)位的字符串依次拼接等于\(s\). \(2\).对于第\(1\)位.第\(l/m+1\)位,第\(2*l/m

AtCoder Grand Contest 014题解

传送门 \(A\) 首先大力猜测一下答案不会很大,所以次数大于\(10^6\)输出\(-1\)就行了 不过我并不会证上界,据说是因为如果\(a=b=c\)且都是偶数肯定\(-1\),否则设\(a\leq b\leq c\),则最大最小值的差为\(c-a\),一次操作之后变成了\({c-a\over 2}\),所以操作次数就是\(\log\)级别的了 typedef long long ll; ll a,b,c,sum;int res; int main(){ scanf("%lld%lld%ll

AtCoder Regular Contest 063 E:Integers on a Tree

题目传送门:https://arc063.contest.atcoder.jp/tasks/arc063_c 题目翻译 给你一个树,上面有\(k\)个点有权值,问你是否能把剩下的\(n-k\)个点全部填上权值,使得每条边链接的两个点权值相差\(1\),如果可以做到需要输出任意一组方案. 题解 我们考虑每条边权值为\(1\)或\(-1\),那么相当于黑白染色一样,所有点权值的奇偶性也都是确定的.如果与读入的\(k\)个点中某个点相冲突了就\(GG\).另外每个点的取值范围都可以转化成一段区间\([

AtCoder Grand Contest 025 Problem D

www.cnblogs.com/shaokele/ AtCoder Grand Contest 025 Problem D Time Limit: 2 Sec Memory Limit: 1024 MB Description Takahashi is doing a research on sets of points in a plane. Takahashi thinks a set \(S\) of points in a coordinate plane is a good set w

AtCoder Grand Contest 024 Problem E(动态规划)

www.cnblogs.com/shaokele/ AtCoder Grand Contest 024 Problem E Time Limit: 2 Sec Memory Limit: 1024 MB Description Find the number of the possible tuples of sequences (\(A_0,A_1,-,A_N\)) that satisfy all of the following conditions, modulo \(M\): ? Fo

AtCoder Grand Contest 011

AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\(n\)个乘客到达了飞机场,现在他们都要坐车离开机场.第\(i\)个乘客到达的时间是\(T_i\),一个乘客必须在\([T_i,T_i+k]\)时刻做到车,否则他会生气.一辆车最多可以坐\(C\)个人.问最少安排几辆车可以让所有人都不生气. 题解 从前往后贪心即可. #include<iostream

【Atcoder Grand Contest 020 E】 Encoding Subsets

Atcoder Grand Contest 020 E 题意:给一个\(0-1\)字符串,如果其中有一段重复,就可以表示成\((\)这一块的表示\(\times\)出现次数\()\). 问这个字符串的所有子集中有多少种表示方法. 思路:考虑\(dp(s)\)表示字符串\(s\)的答案. 那么我们得考虑第一个表示成的位置是什么. ①第一位就是表示的第一位,不参与循环.那么转移到\(dp(s.substr(1))\),并且如果这位是\(1\),那么乘上\(2\),因为这位可能是\(0\). ②一个前