Tarjan笔记1

Posted Q1143316492

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tarjan笔记1相关的知识,希望对你有一定的参考价值。

Tarjan

2822 爱在心中

** 时间限制: 1 s

** 空间限制: 128000 KB

** 题目等级 : 钻石 Diamond

题解

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

codevs2282

1,求大小大于1的强联通个数,强联通缩点后,如果出度为0的强联通个数只有一个,输出这个强联通的元素,否则输出-1

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>

using namespace std;
const int maxn = 1e5+7;
const int maxm = maxn << 2;

int n,m;

struct Node {
    int to,w,next;
} edge[maxm];
int first[maxn],sign;

int dfn[maxn],low[maxn],vis[maxn],inx,cnt,col[maxn],num[maxn];

int outdegree[maxn];

stack<int>s;

void clear_arr() {
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(vis,0,sizeof(vis));
    memset(col,0,sizeof(col));
    memset(num,0,sizeof(num));
    memset(outdegree,0,sizeof(outdegree));
    inx = cnt = 1;
    while(s.size()) {
        s.pop();
    }
}

void init() {
    for(int i = 1; i <= n; i ++ ) {
        first[i] = 0;
    }
    sign = 1;
}

void add_edge(int u,int v,int w) {
    edge[sign].to = v;
    edge[sign].w  = w;
    edge[sign].next = first[u];
    first[u] = sign ++;
}

void tarjan(int x) {
    dfn[x] = low[x] = inx ++;
    s.push(x);
    vis[x] = 1;

    for(int i = first[x]; i ; i = edge[i].next ) {
        int to = edge[i].to;
        if(!dfn[to]) {
            tarjan(to);
            low[x] = min(low[x],low[to]);
        }
        else if(vis[to]) {
            low[x] = min(low[x],dfn[to]);
        }
    }
    int now;
    if(low[x] == dfn[x]) {
        do {
            now = s.top();
            s.pop();
            vis[now] = 0;
            col[now] = cnt;
            num[cnt] ++;
        } while(now != x);
        cnt ++;
    }

}

int main()
{
    int u,v,w;
    while(~scanf("%d %d",&n,&m)) {
        init();
        vector<pair<int,int> >vec;
        for(int i = 1; i <= m; i ++ ) {
            scanf("%d %d",&u,&v);
            add_edge(u,v,1);
            vec.push_back(make_pair(u,v));
        }
        clear_arr();
        for(int i = 1; i <= n; i ++ ) {
            if(!dfn[i]) {
                tarjan(i);
            }
        }

        int god = 0;
        for(int i = 1; i < cnt; i ++ ) {
            if(num[i] > 1) {
                god ++;
            }
        }
        printf("%d\n",god);

        for(int i = 0; i < vec.size(); i ++ ) {
            u = vec[i].first;
            v = vec[i].second;
            if(col[u] != col[v]) {
                outdegree[col[u]] ++;
            }
        }

        int pos = -1, number = 0;
        for(int i = 1; i < cnt ; i ++ ) {
            if(outdegree[i] == 0 && num[i] > 1) {
                pos = i;
                number ++;
            }
        }
        if(number == 1) {
            vector<int>ans;
            for(int i = 1; i <= n; i ++ ) {
                if(col[i] == pos) {
                    ans.push_back(i);
                }
            }
            for(int i = 0; i < ans.size(); i ++ ) {
                if(i == 0) {
                    printf("%d",ans[i]);
                } else {
                    printf(" %d",ans[i]);
                }
            }
            puts("");
        } else {
            puts("-1");
        }
    }

    return 0;
}

以上是关于Tarjan笔记1的主要内容,如果未能解决你的问题,请参考以下文章

算法笔记_144:有向图强连通分量的Tarjan算法(Java)

[学习笔记]tarjan求割边

笔记:LCA最近公共祖先 Tarjan(离线)算法

「学习笔记」tarjan求最近公共祖先

笔记:Tarjan算法 求解有向图强连通分量的线性时间的算法

学习笔记:python3,代码片段(2017)