强连通分量——爱在心中(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 c=getchar();
    while(c>‘9‘||c<‘0‘){if(c==‘-‘)t=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){num=num*10+c-‘0‘;c=getchar();}
    return num*t;
}
const int N=10010;
inline int min(int a,int b){return a<b?a:b;}
vector<int> g[N];stack<int> s;
int n,m,pre[N],low[N],biao[N],cnt=0,t=0,d[N],ans=0,no[N];
void dfs(int x){
    pre[x]=low[x]=++t;s.push(x);
    for(int i=0;i<g[x].size();i++){
        int y=g[x][i];
        if(!pre[y]){dfs(y);low[x]=min(low[x],low[y]);}
        else if(!biao[y])low[x]=min(low[x],pre[y]);
    }
    if(pre[x]==low[x]){
        int st=-1,tmp=0;cnt++;
        while(st!=x){
            st=s.top();s.pop();
            biao[st]=cnt;tmp++;
        }
        if(tmp==1)ans--,no[cnt]=1;
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        g[x].push_back(y);
    }
    for(int i=1;i<=n;i++)
        if(!pre[i])dfs(i);
    printf("%d\n",cnt+ans);
    for(int i=1;i<=n;i++)
        for(int j=0;j<g[i].size();j++)
            if(biao[i]!=biao[g[i][j]])
                d[biao[i]]++;
    int tmp=0;
    for(int i=1;i<=cnt;i++)
        if(d[i]==0)tmp=(tmp==0?i:-1);
    if(tmp==-1||no[tmp]){puts("-1");return 0;}
    for(int i=1;i<=n;i++)
        if(biao[i]==tmp)printf("%d ",i);
    return 0;
}

本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。

时间: 2024-10-25 17:37:30

强连通分量——爱在心中(codevs_2822)——tarjan求scc的相关文章

[图论] 有向图强连通分量 (kosaraju算法,Tarjan算法)

记录自己的想法:在有向图中,如果一些顶点中任意两个顶点都能互相到达(间接或直接),那么这些顶点就构成了一个强连通分量,如果一个顶点没有出度,即它不能到达其他任何顶点,那么该顶点自己就是一个强连通分量.在用kosaraju算法和Tarjan算法求强连通分量的时候,就是给所有的顶点分组染色,同一种颜色的顶点在同一个强连通分量中,记录有多少种颜色(有多少个强联通分量),每个顶点属于哪种颜色(每个顶点在哪个强连通分量重).在同一个强连通分量中的所有顶点可以缩为一个顶点,然后根据缩点构造DAG(有向无环图

强连通分量——消息扩散(洛谷_2002)——tarjan求scc

强连通分量(scc) 缩点 建新图 找入度为0的点 大功告成 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<stack> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c&g

强连通分量——间谍网络(洛谷_1262)——tarjan求scc

scc 缩点 建图 处理 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<stack> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>'9'||c<'0'){i

习题:codevs 2822 爱在心中 解题报告

这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联通分量里面只有这一道题. 题目是这样的: “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是

poj 2186 Popular Cows【tarjan求scc个数&amp;&amp;缩点】【求一个图中可以到达其余所有任意点的点的个数】

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27698   Accepted: 11148 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M &

受欢迎的牛 tarjan求scc模板

第一遍不太熟,第二遍飞快地打出来了 算是tarjan模板了吧,几天了也总算是有一点对tarjan求法过程的理解了. if(!dfn[u])tarjan(u),low[x] = min(low[x],low[u]);//如果没有访问过u,则tarjan一下,如果u走出去搞到的low更小则用这个更新x的low else if(ins[u])low[x] = min(low[x],dfn[u]);//如果u访问过但在栈里,那么u的low说不定已经被更新过了,如果此时令low[x]与low[u]取min

UVALive 4262——Trip Planning——————【Tarjan 求强连通分量个数】

Road Networks Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 4262 Description There is a road network comprised by M<tex2html_verbatim_mark> roads and N<tex2html_verbatim_mark> cities.

【学习整理】Tarjan:强连通分量+割点+割边

Tarjan求强连通分量 在一个有向图中,如果某两点间都有互相到达的路径,那么称中两个点强联通,如果任意两点都强联通,那么称这个图为强联通图:一个有向图的极大强联通子图称为强联通分量.   算法可以在 的时间内求出一个图的所有强联通分量. 表示进入结点 的时间 表示从 所能追溯到的栈中点的最早时间 如果某个点 已经在栈中则更新  否则对 进行回溯,并在回溯后更新  #include<iostream> #include<cstdlib> #include<cstdio>

【转载】有向图强连通分量的Tarjan算法

from byvoid [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components). 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达.{5},{6}也分别是两个强连通分量. 直接根据定义,用双向遍历取交集的方法求强连通分量,时间复杂度为