Problem - D - Codeforces Fix a Tree

Problem - D - Codeforces  Fix a Tree

看完第一名的代码,顿然醒悟。。。

我可以把所有单独的点全部当成线,那么只有线和环。

如果全是线的话,直接线的条数-1,便是操作数。

如果有环和线,环被打开的同时,接入到线上。那就是线和环的总数-1.

如果只有环的话,把所有的环打开,互相接入,共需n次操作。

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 2e5+5;
int cur[maxn];
int pre[maxn];
int Find(int x) {return pre[x] == x ? x : Find(pre[x]);}
int main()
{
    int n;
    scanf("%d",&n);
    int thread = 0;
    int ans = 0;
    for(int i = 1; i<=n; i++) pre[i] = i;
    for(int i = 1; i<=n; i++)
    {
        scanf("%d",&cur[i]);
        if(cur[i]==i)
        {
            thread = i;
            ans++;
        }
        else
        {
            int fx = Find(i);
            int fy = Find(cur[i]);
            if(fx == fy)
            {
                cur[i] = i;
                ans++;
            }
            else
            {
                pre[fx] = fy;
            }
        }
    }
    if(thread==0) //全是环
    {
        for(int i = 1; i<=n; i++)
        {
            if(cur[i]==i)
            {
                thread = i;
                break;
            }
        }
        ans++;
    }
    printf("%d\n",ans-1);
    for(int i = 1; i<=n; i++)
    {
        if(cur[i]==i) cur[i] = thread;
    }
    for(int i = 1; i<n; i++) printf("%d ",cur[i]);
    printf("%d\n",cur[n]);
    return 0;
}
时间: 2024-10-14 14:05:21

Problem - D - Codeforces Fix a Tree的相关文章

Problem E CodeForces 237C

Description You've decided to carry out a survey in the theory of prime numbers. Let us remind you that a prime number is a positive integer that has exactly two distinct positive integer divisors. Consider positive integers a, a + 1, ..., b (a ≤ b).

Problem F CodeForces 16E

Description n fish, numbered from 1 to n, live in a lake. Every day right one pair of fish meet, and the probability of each other pair meeting is the same. If two fish with indexes i and j meet, the first will eat up the second with the probability 

Problem B Codeforces 295B 最短路(floyd)

Description Greg has a weighed directed graph, consisting of n vertices. In this graph any pair of distinct vertices has an edge between them in both directions. Greg loves playing with the graph and now he has invented a new game: The game consists

CodeForces - 383C Propagating tree(dfs + 线段树)

题目大意: 给出一棵树,树上每个节点都有权值,然后有两个操作. 1 x val 在结点x上加上一个值val,x的儿子加上 -val,x的儿子的儿子加上 - (-val),以此类推. 2 x 问x节点的值. 思路分析: 每个节点上加值都是给自己的儿子节点加,而且这个是颗树. 比如样例上的,如果你给node 1加一个值,那么五个节点都加. 再给node 2加个值,2的儿子节点也加了,之前给1加的值也要加到2号节点的儿子. 所以你会发现节点的儿子会存在一个从属的关系. 这样的话,我们可以把所有节点从新

【并查集】【模拟】Codeforces 699D Fix a Tree

题目链接: http://codeforces.com/problemset/problem/699/D 题目大意: 通过给定当前节点的父亲给你一棵有错的树,可能有多个根和环,输出改成正确的一棵树至少要修改几个节点的父亲和修改后所有点的父亲值 题目思路: [并查集][模拟] 用并查集把成环的归在一起(类似强连通分量),然后统计分量数并修改. 第一个出现的当作根,其余的每一块连通分量都去掉一条边改为连接到根上. 1 // 2 //by coolxxx 3 ////<bits/stdc++.h>

【codeforces 698B】 Fix a Tree

题目链接: http://codeforces.com/problemset/problem/698/B 题解: 还是比较简单的.因为每个节点只有一个父亲,可以直接建反图,保证出现的环中只有一条路径. 然后发现,有多少个环,就需要改多少条边.然后设出现连向自己的节点为x,这些也要改边,对答案的贡献应为:$max(x-1,0)$.对于最后的根节点,有自环选一个,没自环在其他环上任选一个点就行. 1 #include<cstdio> 2 inline int min(int a,int b){re

【CodeForces 699D】Fix a Tree

dfs找出联通块个数cnt,当形成环时,令指向已访问过节点的节点变成指向-1,即做一个标记.把它作为该联通图的根. 把所有联通的图变成一颗树,如果存在指向自己的点,那么它所在的联通块就是一个树(n-1条边),选择这样一个点,其它联通块的根指向它,就需要cnt-1次改变.如果都是环(没有指向自己的),那任意选定一个环,拆开,其它环拆开再连到此环上,就需要cnt次改变. #include <cstdio> #define N 200005 int a[N],v[N],h[N],fa[N],q[N]

Codeforces Round #363 Fix a Tree(树 拓扑排序)

先做拓扑排序,再bfs处理 #include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<map>#include<stack>#include<queue>#include<vector>#include<cmath&g

CodeForces 698B Fix a Tree

并查集,构造. 先看一下图的特殊性,按照这种输入方式,一个点的入度最多只有$1$,因此,问题不会特别复杂,画画图就能知道了. 如果给出的序列中已经存在$a[i]=i$,那么随便取一个$a[i]=i$的$i$作为$root$,剩下的每一条边$a[i] \to i$,可以用并查集来处理,如果发现某条边$a[i] \to i$加入前$a[i]$与$i$已经在同一集合中,说明再加$a[i] \to i$会导致成环,因此将$i$的$father$改成$root$即可,并将$i$与$root$合并. 如果给