【强连通分量】vijos 1626 爱在心中

描述

“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”

在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。

如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。

现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。

格式

输入格式

第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。

第2到第M+1行,每行两个数A、B,代表A爱B。

输出格式

第1行,一个数,代表爱的国度里有多少爱心天使。

第2行,如果某个爱心天使被其他所有人和爱心天使所爱则请输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。

样例1

样例输入1[复制]

6 7
1 2
2 3
3 2
4 2
4 5
5 6
6 4

样例输出1[复制]

2
2 3

样例2

样例输入2[复制]

3 3
1 2
2 1
2 3

样例输出2[复制]

1
-1

限制

各个测试点1s

提示

对于40%的数据 N<=10 M<=100
对于80%的数据 N<=100 M<=1000
对于100%的数据 N<=1000 M<=10000

来源

Cai0715 原创
NOIP 2009·Dream Team 模拟赛 第一期 第四题

强连通分量+缩点

因为缩点后的图为有向无环图

所以总会有出度(out_degree)为0的连通分量

而如果出度为0的点只有一个

不难证明所有的连通分量都指向他

PS:

一:这题只有一个人的连通分量不算爱心天使

二:缩点后找到出度为0的点要判断个数 大于1个为-1

三:如果只有一个并且这个点不是一个人

# include<cstdio>
# include<cstring>
# include<stack>
# include<algorithm>
# include<iostream>
using namespace std;
const int N=1000+10;
const int M=10000+10;
stack<int>S;
int n,m,ecnt,scc_cnt,dfs_clock,tot,out_degree,cur;
int fist[N],next[M],v[M],pre[N],low[N],scc_no[N],size[N],out[N];
void built(int a,int b){
    ++ecnt;
    v[ecnt]=b;
    next[ecnt]=fist[a];
    fist[a]=ecnt;
}
void init(){
    int a,b;
    memset(fist,-1,sizeof(fist));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        built(a,b);
    }
}
int dfs(int u){
    int lowu=pre[u]=++dfs_clock;
    S.push(u);
    for(int e=fist[u];e!=-1;e=next[e])
    if(!pre[v[e]])
    lowu=min(lowu,dfs(v[e]));
    else if(!scc_no[v[e]])
    lowu=min(lowu,pre[v[e]]);
    low[u]=lowu;
    if(low[u]==pre[u]){
        scc_cnt++;
        for(;;){
            int x=S.top();S.pop();
            scc_no[x]=scc_cnt;
            if(x==u)break;
        }
    }
    return low[u];
}
void find_scc(){
    memset(pre,0,sizeof(pre));
    memset(low,0,sizeof(low));
    for(int i=1;i<=n;i++)
    if(!pre[i])dfs(i);
}
void work(){
    for(int i=1;i<=n;i++)size[scc_no[i]]++;
    for(int i=1;i<=scc_cnt;i++)if(size[i]>1)tot++;
    printf("%d\n",tot);
    for(int i=1;i<=n;i++)for(int e=fist[i];e!=-1;e=next[e])
    if(scc_no[i]!=scc_no[v[e]])out[scc_no[i]]++;//因为scc_no已经相当于并查集了
    for(int i=1;i<=scc_cnt;i++)if(out[i]==0){out_degree=i;cur++;}
    if(cur>1||size[out_degree]==1){printf("-1");return;}
    for(int i=1;i<=n;i++)if(scc_no[i]==out_degree)printf("%d ",i);
}
int main(){
    init();
    find_scc();
    work();
    return 0;
}
时间: 2024-10-19 22:41:52

【强连通分量】vijos 1626 爱在心中的相关文章

Vijos——T1626 爱在心中

https://vijos.org/p/1626 描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是具有传递性的,即如果A爱B,B爱C,则A也爱C. 如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使. 现在,我们想知道在这个爱的国度里会出现多

强连通分量——爱在心中(codevs_2822)——tarjan求scc

scc 找只有一个节点的强连通分量,标记. 第一行输出强连通分量个数(不为1个节点) 缩点 建图 找出度为0的点. 超过一个或者该点被标记,puts("-1"): else 输出答案. #include<iostream> #include<cstdio> #include<vector> #include<stack> using namespace std; inline int read(){ int t=1,num=0;char

[题解]codevs &amp; vijos 爱在心中

描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是具有传递性的,即如果A爱B,B爱C,则A也爱C. 如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使. 现在,我们想知道在这个爱的国度里会出现多少爱心天使.而且,如果某个爱心天使被其他所有人或爱

【CodeVS2822】爱在心中

Description “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是具有传递性的,即如果A爱B,B爱C,则A也爱C.如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使.现在,我们想知道在这个爱的国度里会出现多少爱心天使.而且,如果某个爱心天使被

爱在心中(codevs 2822)

题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是具有传递性的,即如果A爱B,B爱C,则A也爱C.如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使.现在,我们想知道在这个爱的国度里会出现多少爱心天使.而且,如果某个

2822 爱在心中

2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是具有传递性的,即如果A爱B,B爱C,则A也爱C.如果有这样一部分人,他们彼此都相爱,则他们就超

第四关——图论:强连通分量

14:27:28 写一首十几岁听的情歌,可惜我没在那个时候遇见你,否则我努力活到百岁以后,就刚好爱你一整个世纪  ——<零几年听的情歌> 今天是待在学校的最后一天了,撒花,庆祝!!!那也祝自己十六岁生日快乐 最近肺炎传染有点严重,大家能点外卖点外卖,能躺床躺床,少出门,你肆无忌惮赖在家的机会来了!!! 好了,今天要讲的呢,是要待在家好好学习一下的强连通分量. 概念 连通分量:在无向图中,即为连通子图. 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到v

Kosaraju算法解析: 求解图的强连通分量

1. 定义 连通分量:在无向图中,即为连通子图. 上图中,总共有四个连通分量.顶点A.B.C.D构成了一个连通分量,顶点E构成了一个连通分量,顶点F,G和H,I分别构成了两个连通分量. 强连通分量:有向图中,尽可能多的若干顶点组成的子图中,这些顶点都是相互可到达的,则这些顶点成为一个强连通分量. 上图中有三个强连通分量,分别是a.b.e以及f.g和c.d.h. 2. 连通分量的求解方法 对于一个无向图的连通分量,从连通分量的任意一个顶点开始,进行一次DFS,一定能遍历这个连通分量的所有顶点.所以

POJ 2186 Popular Cows 强连通分量模板

题意 强连通分量,找独立的块 强连通分量裸题 #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <iostream> using namespace std; const int maxn = 50005; int n, m; struct Edge { int v, next;