码迷,mamicode.com
首页 > 其他好文 > 详细

poj2186--tarjan+缩点

时间:2019-08-10 21:31:37      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:style   其他   The   from   连通   open   class   hide   long   

题目大意:

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
 
      先用tarjan求出每个强连通分量,再缩点,统计每个点的出度,如果有且只有1个出度为0的点,就输出这个点包含的节点数,否则输出0.
 
证明:
      如果有强连通分量被孤立(即和其他强连通分量无边相连),那么答案一定是0,此时由于缩点后是一个DAG图,出度为0的点的个数一定大于1.
      如果没有点被孤立,当出度为0的点多于1个时,由DAG图的性质可得,一定不存在一个点能从其他所有点到达。只有当出度为0的点的个数等于1时,这个出度为0的点才能被其他所有点到达。
 
技术图片
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define cls(s,h) memset(s,h,sizeof s)
const int maxn = 1e5 + 7;
int n , m ;
int tot;
struct  edge
{
    int to,from,nxt;
}e[maxn << 1];

int head[maxn];
void add_edge(int u , int v ){
    e[tot].from = u ;
    e[tot].to = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}

int stack[maxn << 1],low[maxn << 1],dfn[maxn << 1];
int scc,sz[maxn << 1],c[maxn << 1],st,num;
void init(){
    cls(head,-1);
    cls(e,0);
    cls(sz,0);
    scc = 0;
    st = 0;
}


void tanjan(int u){
    stack[++st] = u;
    dfn[u] = low[u] = ++ num;
    for(int i = head[u],v; ~i ;i = e[i].nxt){
        if(c[v = e[i].to]) continue;
        if(dfn[v]) low[u] = min(low[u],dfn[v]);
        else tanjan(v),low[u] = min(low[u],low[v]);
    }
    if(low[u] == dfn[u]){
        c[u] = ++ scc; sz[scc] = 1;
        while(st && u != stack[st])
            //SCC number and the scc ge SCC
            c[stack[st--]] = scc,sz[scc] ++;
        st--;
    }
}

int out[maxn << 1];
int main(int argc, char const *argv[])
{
    init();
    scanf("%d %d",&n,&m);
    for(int i = 1,u,v;i <= m ;i ++)
    scanf("%d %d",&u,&v),add_edge(u,v);
    
    for(int i = 1;i <= n;i ++)
        if(!dfn[i]) tanjan(i);
    for(int i = 0;i < tot;i ++)
        if(c[e[i].from] != c[e[i].to]) out[c[e[i].from]] ++;
    int ans = 0;
    for(int i = 1;i <= scc;i ++)
        if(!out[i]) ans = ans ? -1: i;
    if(~ans) ans = sz[ans];
    else ans = 0;
    printf("%d\n", ans);
    return 0;
}
View Code

 

poj2186--tarjan+缩点

标签:style   其他   The   from   连通   open   class   hide   long   

原文地址:https://www.cnblogs.com/DWVictor/p/11332838.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!