codves 2822 爱在心中 && bzoj 1051: [HAOI2006]受欢迎的牛
2822 爱在心中
时间限制: 1 s 空间限制: 128000 KB
题目描述 Description
“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”
在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。
如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。
现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。
输入描述 Input Description
第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。
第2到第M+1行,每行两个数A、B,代表A爱B。
输出描述 Output Description
第1行,一个数,代表爱的国度里有多少爱心天使。
第2行,如果某个爱心天使被其他所有人和爱心天使所爱则请输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。
样例输入 Sample Input
样例输入1:
6 7
1 2
2 3
3 2
4 2
4 5
5 6
6 4
样例输入2:
3 3
1 2
2 1
2 3
样例输出 Sample Output
样例输出1:
2
2 3
样例输出2:
1
-1
数据范围及提示 Data Size & Hint
各个测试点1s
解:强联通分量;
#include<cstdio> #include<cstring> #include<algorithm> using std::min; const int N=100010; struct node{int next,to,from;}e[N]; int first[N]; int book[N]; int dfn[N],low[N],stack[N],cd[N]; int cnt=0; void insert(int v,int u) { e[++cnt].to=u;e[cnt].from=v;e[cnt].next=first[v];first[v]=cnt; } int tot=0,top=0,num=0; int size[N],color[N]; void tarjan(int x) { dfn[x]=low[x]=++tot; book[x]=1;stack[++top]=x; for(int i=first[x];i;i=e[i].next) { if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]); else if(book[e[i].to]) low[x]=min(low[x],low[e[i].to]); } if(dfn[x]==low[x]) { ++num; while(stack[top]!=x) { book[stack[top]]=0; color[stack[top]]=num; size[num]++; top--; } book[x]=0; color[x]=num; size[num]++; top--; } } int main() { int n,m; scanf("%d %d",&n,&m); int v,u; for(int i=1;i<=m;i++) { scanf("%d %d",&v,&u); insert(v,u); } int ans=0; for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=num;i++) if(size[i]!=1) ans++; printf("%d\n",ans); cnt=0; memset(first,0,sizeof(first)); for(int i=1;i<=m;i++) if(color[e[i].from]!=color[e[i].to]) cd[color[e[i].from]]++,insert(color[e[i].from],color[e[i].to]); ans=0; int aim=0; for(int i=1;i<=num;i++) if(!cd[i]) ans++,aim=i; if(ans!=1) printf("-1"); else { if(size[aim]==1) printf("-1"); else for(int i=1;i<=n;i++) if(color[i]==aim) printf("%d ",i); } return 0; }
--------------
1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBDescription
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
1 2
2 1
2 3
Sample Output
1
HINT
100%的数据N<=10000,M<=50000
解:同上;
强联通分量大多要in,cd;
#include<cstdio> #include<cstring> #include<algorithm> using std::min; const int N=100010; struct node{int next,to,from;}e[N]; int first[N]; int book[N]; int dfn[N],low[N],stack[N],cd[N]; int cnt=0; void insert(int v,int u) { e[++cnt].to=u;e[cnt].from=v;e[cnt].next=first[v];first[v]=cnt; } int tot=0,top=0,num=0; int size[N],color[N]; void tarjan(int x) { dfn[x]=low[x]=++tot; book[x]=1;stack[++top]=x; for(int i=first[x];i;i=e[i].next) { if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]); else if(book[e[i].to]) low[x]=min(low[x],low[e[i].to]); } if(dfn[x]==low[x]) { ++num; while(stack[top]!=x) { book[stack[top]]=0; color[stack[top]]=num; size[num]++; top--; } book[x]=0; color[x]=num; size[num]++; top--; } } int main() { int n,m; scanf("%d %d",&n,&m); int v,u; for(int i=1;i<=m;i++) { scanf("%d %d",&v,&u); insert(v,u); } int ans=0; for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=num;i++) if(size[i]!=1) ans++; cnt=0; memset(first,0,sizeof(first)); for(int i=1;i<=m;i++) if(color[e[i].from]!=color[e[i].to]) cd[color[e[i].from]]++,insert(color[e[i].from],color[e[i].to]); ans=0; int aim; for(int i=1;i<=num;i++) if(!cd[i]) ans++,aim=i; if(ans!=1) printf("0"); else printf("%d\n",size[aim]); return 0; }
----------