博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
codevs 2822 爱在心中(强连通分量)
阅读量:4360 次
发布时间:2019-06-07

本文共 2813 字,大约阅读时间需要 9 分钟。

题目描述 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

思路:先用Tarjan算法求强连通分量,统计强连通点的个数,输出。若出度为0的强连通点只有一个且里面包含的元素>1,则输出这个点里包含的元素,否则输出-1。

题解:

#include
#include
#include
#include
using namespace std;const int maxn=100000+10;struct cc{ int from,to;}es[maxn];int first[maxn],next[maxn];int tot=0;void build(int ff,int tt){ es[++tot]=(cc){ff,tt}; next[tot]=first[ff]; first[ff]=tot;}bool vis[maxn];int pre[maxn],scc_num[maxn],cnt,scc_cnt;stack
q;int dfs(int u){ int lowu=pre[u]=++cnt; q.push(u); vis[u]=1; for(int i=first[u];i;i=next[i]) { int v=es[i].to; if(!pre[v]) { int lowv=dfs(v); lowu=min(lowu,lowv); } else if(!scc_num[v]) { lowu=min(lowu,pre[v]); } } if(lowu==pre[u]) { scc_cnt++; while(1) { int v=q.top(); q.pop(); scc_num[v]=scc_cnt; if(u==v) { break; } } } return lowu;}int s[maxn];int chu[maxn],color[maxn];int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); build(x,y); } for(int i=1;i<=n;i++) { if(!pre[i]) { dfs(i); } } for(int i=1;i<=n;i++) { for(int j=first[i];j;j=next[j]) { int u=es[j].to; if(scc_num[i]!=scc_num[u])//不在一个强连通图中 { chu[scc_num[i]]++; } } } int ans1=0,ans2=0,t; for(int i=1;i<=n;i++)//计算强连通点的大小 { s[scc_num[i]]++; } for(int i=1;i<=scc_cnt;i++) { if(s[i]>1)//计算爱心天使数 { ans1++; } if(!chu[i])//找出度为0的点 { ans2++; t=i; } } printf("%d\n",ans1); if(ans2==1&&s[t]!=1)//只能有一个出度为0的点 { for(int i=1;i<=n;i++) { if(scc_num[i]==t) { printf("%d ",i);//输出里面的点 } } } else { printf("-1"); } return 0;}

转载于:https://www.cnblogs.com/-feather/p/7779905.html

你可能感兴趣的文章
物联网架构成长之路(8)-EMQ-Hook了解、连接Kafka发送消息
查看>>
2018-2019-1 20165234 20165236 实验二 固件程序设计
查看>>
IDEA的GUI连接数据库写入SQL语句的问题总结
查看>>
Xpath在选择器中正确,在代码中返回的是空列表问题
查看>>
leecode第一百九十八题(打家劫舍)
查看>>
【BZOJ 1233】 [Usaco2009Open]干草堆tower (单调队列优化DP)
查看>>
07-3. 数素数 (20)
查看>>
写一个欢迎页node统计接口Py脚本(邮件,附件)-py
查看>>
计算两个日期之间的天数
查看>>
Android关于buildToolVersion与CompileSdkVersion的区别
查看>>
袋鼠云日志,日志分析没那么容易
查看>>
缓存穿透 缓存雪崩 缓存并发
查看>>
了解你的Linux系统:必须掌握的20个命令
查看>>
js setInterval 启用&停止
查看>>
knockoutJS学习笔记04:监控属性
查看>>
Linux下启动/关闭Oracle
查看>>
session和cookie的区别
查看>>
alert弹出窗口,点击确认后关闭页面
查看>>
oracle问题之数据库恢复(三)
查看>>
单点登陆(SSO)
查看>>