【codevs2822】爱在心中 tarjan 缩点+理解

【codevs2822】爱在心中

2014年1月26日5580

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

代码

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define inf 10000000
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘)f=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘)
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return x*f;
}
//***************************************************************

struct ss
{
    int u,to,next;
} e[50001];
int out[40001];
int head[50001],vis[50001],dfn[50001],low[50001],belong[50001],hav[50001];
int q[50001],inq[50001];
int t=1,bcnt,cnt,n,m,top;
void add(int u,int v)
{
    e[t].to=v;
    e[t].u=u;
    e[t].next=head[u];
    head[u]=t++;
}
void dfs(int u)
{
    vis[u]=inq[u]=1;
    low[u]=dfn[u]=++cnt;
    q[++top]=u;
    for(int i=head[u]; i; i=e[i].next)
    {
        if(!vis[e[i].to])
        {
            dfs(e[i].to);
            low[u]=min(low[u],low[e[i].to]);
        }
        else if(inq[e[i].to])low[u]=min(low[u],dfn[e[i].to]);
    }
    int v=-1;
    if(low[u]==dfn[u])
    {
        bcnt++;
        while(v!=u)
        {
            v=q[top--];
            inq[v]=0;
            belong[v]=bcnt;
            hav[bcnt]++;
        }
    }
}
void rebuild()
{

    for(int i=1; i<=m; i++)
    {
        if(belong[e[i].u]!=belong[e[i].to])
        {
            out[belong[e[i].u]]++;
        }
    }
}
void tarjan()
{
    for(int i=1; i<=n; i++)
    {
        if(!vis[i])
        {
            dfs(i);
        }
    }
    rebuild();
}
void work()
{
    int res=0;
    int ans;
    for(int i=1; i<=bcnt; i++)
    {
        if(out[i]==0)
        {
            ans=i;
            res++;
        }
    }
    int bb=0;
    for(int i=1;i<=bcnt;i++)
    {
        if(hav[i]>=2)bb++;
    }
    cout<<bb<<endl;
    if(res==1)
    {
        if(hav[ans]!=1)
        {
            int kk=0;
            int hh[50001];
            for(int i=1; i<=n; i++)
            {
                if(belong[i]==ans)
                {
                    hh[++kk]=i;
                }
            }
            for(int i=1; i<kk; i++)
            {
                printf("%d ",hh[i]);
            }
            cout<<hh[kk]<<endl;
        }
        else cout<<-1<<endl;

    }
    else cout<<-1<<endl;
}
int main()
{
    int u,v;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    tarjan();
    work();
    return 0;
}
时间: 2025-01-19 22:34:57

【codevs2822】爱在心中 tarjan 缩点+理解的相关文章

[CodeVS2822]爱在心中

思路:Tarjan+缩点.首先跑一遍Tarjan,统计结点个数大于$1$的连通分量个数.然后寻找统计结点个数大于$1$且出度为$0$的连通分量,若只存在一个这样的连通分量,输出其点集即可. 1 #include<stack> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 inline int getint() { 6 char ch; 7 while(!isdigit(ch=getcha

codevs 2822 爱在心中 tarjan(强联通分量)

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

【CodeVS 2822】爱在心中

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

【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案

初涉tarjan缩点

tarjan缩点:口胡过好多题,不过从来没写过…… 什么是缩点 tarjan和Kosaraju.Gabow算法一样,是为了求有向图中的强连通分量.因为有向图中大多数情况下会有环存在,而有环是一个不甚好的性质.如果把有向图里的所有强连通分量都看作是一个点(缩点),则原图就会变成一个DAG——DAG是一个好东西. 什么是tarjan缩点 tarjan算法网上大多有介绍,我也在之前看过多次,不过从未写过,这里不再介绍. 今天把核心代码重新看了一遍,终于深入理解了其算法.那么就不妨在这里直接放上代码.

【luogu3387】 【模板】缩点 [tarjan 缩点]

P3387 [模板]缩点 静下心来去看 其实真的很好理解 突然搞不懂我之前为什么死活都看不懂 参悟了学长的代码还有BYVoid的讲解 放一下BYVoid大佬的tarjan伪代码 帮助理解 还有各种变量的含义 (from黄学长 栈里的元素表示的是当前已经访问过但是没有被归类到任一强连通分量的结点dfn[u] 表示结点 u 在 DFS 中第一次搜索到的次序,通常被叫做时间戳 ow[u] 它表示从 u 或者以 u 为根的子树中的结点,再通过一条反祖边或者横叉边可以到达的时间戳最小的结点 v 的时间戳,

tarjan缩点与割点

Tarjan算法 先是废话时间:说来挺惭愧 , 好几个月以前就学过tarjan算法然而现在才第一次写 模板题:[luogu P3387][模板]缩点 tarjan缩点&dp 为啥要缩点答案显然 把环缩成一个点 然后图上拓扑dp tarjan同名算法有很多 , 比如本blog的缩点与割点的tarjan算法其实并不是一个东西 , 但是很是相似 这个tarjan , 需要三个东西 第一:一个栈来存放搜到的点 第二:一个时间戳dfn , 表示第几个搜到这个点的 第三:low数组 , 表示够追溯到的最早的

【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 318[Submit][Status][Discuss] Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti.Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意

POJ1523(求连用分量数目,tarjan算法原理理解)

SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7406   Accepted: 3363 Description Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a