noip201506 Message 信息传递

试题描述:

有 n 个同学(编号为 1 到 n )正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为 i 的同学的信息传递对象是编号为 T_i 的同学。游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息, 但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自 己的生日时,游戏结束。请问该游戏一共可以进行几轮?

输入:

共2行,第1行包含1个正整数 n ,表示 n 个人。
第2行包含 n 个用空格隔开的正整数T_1,T_2,...,T_n ,其中第 i 个整数 T_i 表示编号为 i 的同学的信息传递对象是编号为 T_i 的同学, T_i <= n 且 T_i 不等于 i 。
数据保证游戏一定会结束。

输出:

共1行,包含1个整数,表示游戏一共可以进行多少轮。

输入示例:

5
2 4 2 3 1

输出示例:

3

数据范围:

n<=200000

--------------------------------------------分隔线--------------------------------------------------------

这题看了题就知道其实我们所要干的一件事就是找最小环……(其实我考试的时候也知道是要最小环,可不知道怎么找啊……于是乎写了一个根本错的东西但不知道怎么回事还蒙了30分……学了一年C++,就差这么一道题的70,我的省一啊……)

上面的废话选择性忽略好了……下面来说这道题的重点……

找最小环的话果断要用到强连通分量。

强连通分量:对于一个有向图的顶点的子集S,如果在S内任取两个顶点u和v,都能找到一条从u到v的路径,那么就称S是强连通的。如果在强连通的顶点集合S中加入其他任意顶点集合后,它都不再是强连通的,那么就称S是原图的一个强连通分量(SCC :Strongly Connected Component)

强连通分量的分解可以用两次简单的dfs来实现。

第一次dfs的时候,选取任意顶点作为起点,遍历所有未访问过的顶点,在回溯前给定点标号。对剩余未访问过的顶点不断重复上述过程。

完成标号后越接近图的尾部,定点的标号越小。

第二次dfs时先将所有的边反向,然后以标号最大的顶点为起点进行dfs,这样可以把图的拓扑序储存。

代码如下:

 1 #include<iostream>
 2 #include<cctype>
 3 using namespace std;
 4 const int MAXN=200000+10;
 5 void read(int &x){
 6     x=0;int f=1;char ch=getchar();
 7     for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1;
 8     for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;
 9     x*=f;
10 }
11 //----------------------
12 int v[MAXN],first[MAXN],next[MAXN],e;
13 void AddEdge(int a,int b){
14     v[++e]=b;
15     next[e]=first[a];
16     first[a]=e;
17 }
18
19 int vr[MAXN],firstr[MAXN],nextr[MAXN],er;
20 void AddEdger(int a,int b){
21     vr[++er]=b;
22     nextr[er]=firstr[a];
23     firstr[a]=er;
24 }
25 //----------------------
26 int n,tot,vs[MAXN],topo[MAXN];
27 bool vis[MAXN];
28 void dfs(int x){
29     vis[x]=1;
30     for(int i=first[x];i;i=next[i])
31         if(!vis[v[i]])dfs(v[i]);
32     vs[++tot]=x;
33 }
34
35 void dfsr(int x,int k){
36     vis[x]=1;
37     topo[x]=k;
38     for(int i=firstr[x];i;i=nextr[i])
39         if(!vis[vr[i]])dfsr(vr[i],k);
40 }
41 //---------------------------
42 int cnt[MAXN];
43 int main(){
44     read(n);
45     for(int i=1;i<=n;i++){
46         int tmp;
47         read(tmp);
48         AddEdge(i,tmp);
49         AddEdger(tmp,i);
50     }
51
52     memset(vis,0,sizeof(vis));
53     for(int i=1;i<=n;i++)
54         if(!vis[i])dfs(i);
55
56     int k=1;
57     memset(vis,0,sizeof(vis));
58     for(int i=n;i>=1;i--)
59         if(!vis[vs[i]])dfsr(vs[i],k++);
60
61     for(int i=1;i<=n;i++)cnt[topo[i]]++;
62     int ans=-1u>>1;
63     for(int i=1;i<=topo[vs[1]];i++){
64         if(cnt[i]!=1)ans=min(ans,cnt[i]);
65     }
66     printf("%d\n",ans);
67 }

时间: 2024-10-16 18:11:46

noip201506 Message 信息传递的相关文章

[NOIP2015]信息传递

[NOIP2015]信息传递[问题描述]有??个同学(编号为1到??)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为?? 的同学的信息传递对象是编号为????的同学.游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象).当有人从别人口中得知自己的生日时,游戏结束.请问该游戏一共可以进行几轮?[输入格式]输入文件名为m

表单提交时如何将错误信息传递到页面中,并且保存原来提交数据

曾经何时,你还有我或许都在困惑,如何方便的将验证不通过的表单信息再返回到前台页面,例如我注册一个账号,辛辛苦苦填写了N多项,一个格式验证没有通过,一切都需要充填,虽然Ajax可以解决这个问题,但是我们总不能把所有表单提交都弄成ajax,更何况有若干人就是没事把javascript给禁止了.哎哎,好了解决方案来了,下面以用户登录为例,说说我的解决方案. 服务器端用nodejs实现: login.html 简单的提交表单 <form action="" id="loginF

noip2015 信息传递 强连通块

时隔好久,重新把那些题找出来,写一写了,毕竟实力还很有限,得学. 一开始,最大的疑惑还是怕一个环里有另外一个环(毕竟经验不丰富),后来看到了这段话 T2 信息传递 大意:在一个只有n条有向边的图中,每个结点出度为1,求一个包含节点数最少的环. 分析:因为只有n条边并且每个点都有且仅有一条边连出去,所以只可能存在简单环,不会出现那种8字形的环套环. 证明:每个点有两种情况:1.不在任何一个环中 这样的点可以直接忽略掉,看成是有n-1个点,n-1条边来证明就行了.2.在某个环中.那么如果我们现在有了

android优化(json工具,message新建/传递,avtivity深入学习视频)

1,在线json校验工具:www.bejson.com 2, 在handler中常用的 message的传递上,message.what使用静态量 . private static final int MSG_SUCCESSS=0X111;message.what=MSG_SUCCESS; 3,Message传递优化,对象新建方式. 普通:Message msg=new Message();.....handler.sendMessage(msg); 修改为:Message msg = hand

NOIP 2015:信息传递

题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象).当有人从别人口中得知自己的生日时,游戏结束.请问该游戏一共可以进行几轮? 输入输出格式 输入格式: 输入共2行. 第1行包含1个正整数n表示

洛谷P2661 信息传递 类似tarjan 强连通 灌水

洛谷P2661 信息传递类似tarjan 强连通 灌水 题意 求一个特殊的图的最小环 这个图 有一个性质 每个点只有一条出边 这样满足一个性质,一张图只有 一个环,以及别的连向他们的边都是一些连向 或者 间接连向这个环的树枝 这些树枝一定不会连成环,因为 每个点只有一条出边,而不可能有两条,所以只要把这些树枝边都删掉,然后再类似tarjan一样跑一遍灌水就行了 先说一下思路,这整道题就是给你几个带枝叶的环要你求最短环而已,于是在输入的时候可以把图中每个点的入度记录下来,然后再删除那些入度为0的点

洛谷P2661 信息传递==coedevs4511 信息传递 NOIP2015 day1 T2

P2661 信息传递 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象).当有人从别人口中得知自己的生日时,游戏结束.请问该游戏一共可以进行几轮? 输入输出格式 输入格式: 输入共2行. 第1

【NOIP2015】信息传递

Description 有个同学(编号为 1 到)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为的同学的信息传递对象是编号为的同学.游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象).当有人从别人口中得知自己的生日时,游戏结束.请问该游戏一共可以进行几轮? Input 输入共 2行. 第 1行包含1个正整数n,表示

2015 NOIP day2 t2 信息传递 tarjan

信息传递 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.luogu.org/problem/show?pid=2661 Description 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里 获