vijos1023 Victoria的舞会3
描述
Victoria是一位颇有成就的艺术家,他因油画作品《我爱北京天安门》闻名于世界。现在,他为了报答帮助他的同行们,准备开一个舞会。
Victoria准备邀请n个已经确定的人,可是问题来了:
这n个人每一个人都有一个小花名册,名册里面写着他能够通知到的人的名字。比如说在A的人名单里写了B,那么表示A能够通知到B;但是B的名单里不见的有A,也就是说B不见得通知到A。
Victoria觉得需要确定自己需要通知多少个人m,能够实际将所有人n都通知到。并求出一种方案以确定m的最小值是多少。
注意:自己的名单里面不会有自己的名字。Victoria可以自身通知到所有n个人。
格式
输入格式
第一行一个数n。接下来n行,每i+1行表示编号为i的人的小花名册名单,名单以0结束。\
1<=n<=200。
输出格式
一个数,m。
样例1
样例输入1
18
0
11 0
0
0
0
16 0
14 0
0
0
0
2 13 0
0
11 0
7 0
0
6 0
0
0
样例输出1
14
限制
各个测试点1s
来源
Vivian Snow
这个题的大意其实就是每个点都有一些子节点,你需要选最少的点,使得这些点与它们的子节点构成整个点集
数据范围这么小,随便瞎搞就好了。。。
我直接先找入度为0的点,然后dfs并标记,剩下未标记的点就都是环了,那么你只要随机选环上的一个点,然后再dfs标记,直到所有点被标记就好了
时间复杂度应该是O(N)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // 2 // 1023.cpp 3 // 4 // 5 // Created by 张淇 on 2017/10/1. 6 // 7 8 #include<iostream> 9 #include<cstdio> 10 #include<cstdlib> 11 using namespace std; 12 struct edge{ 13 int go,next; 14 }e[2010]; 15 int n,tot,head[2010],in[2010]; 16 int h=1,t,q[2010]; 17 int book[2010]; 18 int ans,cnt; 19 void insert(int u,int v){ 20 e[++tot].go=v;e[tot].next=head[u];head[u]=tot; 21 } 22 void dfs(int x){ 23 for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 24 if(!book[y]){ 25 book[y]=1; 26 cnt++; 27 dfs(y); 28 } 29 } 30 void topsort(){ 31 for(int i=1;i<=n;i++) 32 if(!in[i]){ 33 book[i]=1; 34 q[++t]=i; 35 //cout<<i<<'\n'; 36 } 37 while(h<=t){ 38 ans++; 39 int x=q[h];h++;cnt++; 40 dfs(x); 41 } 42 if(cnt!=n) 43 for(int i=1;i<=n;i++) 44 if(!book[i]){ 45 //cout<<i<<endl; 46 ans++;cnt++; 47 book[i]=1; 48 dfs(i); 49 } 50 } 51 int main(){ 52 //freopen("input.txt","r",stdin); 53 ios_base::sync_with_stdio(false); 54 cin.tie(0); 55 cin>>n; 56 for(int i=1;i<=n;i++){ 57 int x; 58 cin>>x; 59 while(x!=0){ 60 insert(i,x); 61 in[x]++; 62 cin>>x; 63 } 64 } 65 topsort(); 66 cout<<ans<<'\n'; 67 }