ZROI#1006

ZROI#1006

可能一眼看起来是个很不可做的题,但你仔细思考一下,你发现.....给的是个\(n\)个点\(n\)条边的东西...
那么它可能是个啥呢?
是个基环树?是个森林+环?是个基环树+森林?
都是有可能的!
然后我们发现,答案就是连通块个数+环数-1.
为什么呢?
假设有\(x\)个连通块,\(y\)个环,那么对于连通块我们一定有一个作为答案连通块,其余的都要接在这下面,且只需修改根即可,所以连通块对答案的贡献是\(x-1\),而对于环,必须拆开,且只需要断开一处成为链接在答案连通块之下即可,所以环的贡献是\(y\).

可得答案即为\(x+y-1\).

\(Code:\)

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#define MEM(x,y) memset ( x , y , sizeof ( x ) )
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define per(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define pii pair < int , int >
#define one first
#define two second
#define rint read<int>
#define pb push_back

using std::queue ;
using std::set ;
using std::pair ;
using std::max ;
using std::min ;
using std::priority_queue ;
using std::vector ;
using std::swap ;
using std::sort ;
using std::unique ;
using std::greater ;

template < class T >
    inline T read () {
        T x = 0 , f = 1 ; char ch = getchar () ;
        while ( ch < '0' || ch > '9' ) {
            if ( ch == '-' ) f = - 1 ;
            ch = getchar () ;
        }
       while ( ch >= '0' && ch <= '9' ) {
            x = ( x << 3 ) + ( x << 1 ) + ( ch - 48 ) ;
            ch = getchar () ;
       }
   return f * x ;
}

const int N = 2e5 + 100 ;
struct edge { int to , next ; } e[N] ;
int head[N] , tot ;
int n , f[N] , ans , cnt , in[N] , siz = 0 ;
queue < int > q ; bool vis[N] , founded ;

inline void build (int u , int v) {
    e[++tot].next = head[u] ;
    head[u] = tot ; e[tot].to = v ;
}

inline void topsort () {
    rep ( i , 1 , n ) if ( ! in[i] ) q.push ( i ) ;
    while ( ! q.empty () ) {
        int j = q.front () ; q.pop () ; vis[j] = true ;
        for (int i = head[j] ; i ; i = e[i].next)
        { int k = e[i].to ; -- in[k] ; if ( ! in[k] ) q.push ( k ) ; }
    }
    return ;
}

inline void dfs (int cur) {
    vis[cur] = true ; ++ siz ;
    for (int i = head[cur] ; i ; i = e[i].next)
        if ( ! vis[e[i].to] ) dfs ( e[i].to ) ;
    return ;
}

int main (int argc , char * argv[]) {
    n = rint () ;
    rep ( i , 1 , n ) {
        f[i] = rint () ;
        build ( i , f[i] ) ;
        ++ in[f[i]] ;
    }
    topsort () ;
    rep ( i , 1 , n )
        if ( ! vis[i] ) {
            siz = 0 ; dfs ( i ) ;
            if ( siz == 1 && ! founded ) founded ^= 1 ;
            else ++ ans ;
        }
    printf ("%d\n" , ans ) ;
    return 0 ;
}

原文地址:https://www.cnblogs.com/Equinox-Flower/p/11572101.html

时间: 2024-08-30 17:52:51

ZROI#1006的相关文章

PAT 1006 换个格式输出 C语言

让我们用字母B来表示"百".字母S表示"十",用"12...n"来表示个位数字n(<10),换个格式来输出任一个不超过3位的正整数.例如234应该被输出为BBSSS1234,因为它有2个"百".3个"十".以及个位的4. 输入格式:每个测试输入包含1个测试用例,给出正整数n(<1000). 输出格式:每个测试用例的输出占一行,用规定的格式输出n. 输入样例1: 234 输出样例1: BBSSS1

TypeError: Error #1006: value 不是函数。

1.错误原因 TypeError: Error #1006: value 不是函数. at BasicChart/dataFunc()[E:\Flash Builder\Map\src\BasicChart.mxml:68] at mx.charts.chartClasses::Series/cacheDefaultValues()[E:\dev\4.0.0\frameworks\projects\datavisualization\src\mx\charts\chartClasses\Seri

解决openstack “failed to connect to server (code: 1006)”故障一例

openstack版本环境:ocata 安装完成ocata版本后,新建主机实例后,通过管理端进入主机实例的控制台时,报错:"failed to connect to server (code: 1006)" 解决思路: 1.检查日志文件,通过日志寻找原因. tail -f /var/log/nova/nova-novncproxy.log 发现连接5900时出现"Name or service not known" 2017-05-17 17:01:43.994 7

问题 1006: C语言程序设计教程(第三版)课后习题5.4

/******************************************************************** @file Main.cpp @date 2017-05-07 @author Zoro_Tiger @brief 问题 1006: C语言程序设计教程(第三版)课后习题5.4 http://www.dotcpp.com/oj/problem1006.html *************************************************

生理周期,POJ(1006)

题目链接:http://poj.org/problem?id=1006 解题报告: 1.枚举天数的时候可以根据前面的结果直接跳过一些错误的答案. ///三个周期是23,28,33, #include <stdio.h> int main() { int p,e,i,d,Case=1; while(scanf("%d%d%d%d",&p,&e,&i,&d),p!=-1) { int t1=p%23,t2=e%28,t3=i%33;///三个周期

solution for 1006 中国剩余定理

一.要求 http://poj.org/problem?id=1006 Biorhythms Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 124113   Accepted: 39154 Description Some people believe that there are three cycles in a person's life that start the day he or she is born.

【BZOJ】1006 神奇的国度

[解析]完美消除序列+染色 [Analysis] 由题知他们的关系构成一个弦图,所以求出完美消除序列一定是成立的. 先求出,然后根据序列来染色,尽可能染小的. 其实时间戳那里用个线段树+二分好像也不错,甚至树状数组都可以,因为元素的变化是单调的... 在此给出证明: 首先进行以下的定义: 团数:最大团的大小. 色数:染色最少用的颜色. ∵团中颜色要两两不同 ∴团数<=色数 ∵我们对序列的染色共染了t种颜色且这样的染色是合法的,但是暂时不能保证最少. ∴t>=色数. 又∵我们的染色方法是贪心的,

1006. 换个格式输出整数

1006. 换个格式输出整数 (15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 让我们用字母B来表示“百”.字母S表示“十”,用“12...n”来表示个位数字n(<10),换个格式来输出任一个不超过3位的正整数.例如234应该被输出为BBSSS1234,因为它有2个“百”.3个“十”.以及个位的4. 输入格式:每个测试输入包含1个测试用例,给出正整数n(<1000). 输出格式:每个测试用例的输出占一

1006 小明与隔壁老王之间不得不说的故事

1006: 小明与隔壁老王之间不得不说的故事 时间限制: 1 Sec  内存限制: 128 MB提交: 355  解决: 152[提交][状态][讨论版] 题目描述 有一天,小明想偷吃隔壁老王院子里苹果树上的苹果. 但是,老王家有一条哈士奇,每隔一定时间就会吼叫.准确的说,它会在一个时间点吼叫第一次,之后每隔一段时间吼叫两次,比如第一次吼叫是在 t 时刻,间隔为 s,则吼叫时间点为 t, t + s, t + s + 1, t + 2s, t + 2s + 1 等. 小明是个要面子的人,不想被这