USACO 2003 Fall Orange Popular Cows /// tarjan缩点 oj22833

题目大意:

n头牛,m个崇拜关系,并且崇拜具有传递性

如果a崇拜b,b崇拜c,则a崇拜c

求最后有几头牛被所有牛崇拜

强连通分量内任意两点都能互达 所以只要强联通分量内有一点是 那么其它点也都会是

按照崇拜关系 即a崇拜b就连一条a到b的边 tarjan求得所有强联通分量染色

而把一个强联通分量缩成一个超级点后 整个图的崇拜关系就变成了一个 有向无环图

此时被所有牛崇拜的牛就是 一个出度为0的超级点

只要把所有边再走一遍就可以计算出度 同时计算每个超级点内有多少个点

即从a出发到b的边 若a b的颜色相同说明是在同一个超级点内那么点数+1 颜色不同那么a的出度+1

但当出现 多个出度为0的超级点 时 必然存在一个出度为0的超级点不被另一个出度为0的超级点崇拜

那么就不满足被所有牛崇拜这个条件 此时答案为 0

#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;

const int N=10005;
struct EDGE { int to, nt; }e[5*N];
int head[N], tot;
int dfn[N], low[N], ind;
int col[N], id;
bool vis[N];
stack <int> s;

int n, m, cnt[N], du[N];

void init() {
    while(!s.empty()) s.pop();
    for(int i=0;i<=n;i++) {
        head[i]=dfn[i]=low[i]=col[i]=-1;
        vis[i]=cnt[i]=du[i]=0;
    }
    tot=ind=id=0;
}
void addE(int u,int v) {
    e[tot].to=v;
    e[tot].nt=head[u];
    head[u]=tot++;
}

void tarjan(int u) {
    dfn[u]=low[u]=ind++;
    s.push(u); vis[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nt) {
        int v=e[i].to;
        if(dfn[v]==-1) {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        } else {
            if(vis[v]) low[u]=min(low[u],low[v]);
        }
    }
    if(dfn[u]==low[u]) {
        col[u]=++id;
        vis[u]=0;
        while(s.top()!=u) {
            col[s.top()]=id;
            vis[s.top()]=0;
            s.pop();
        } s.pop();
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m)) {
        init();
        for(int i=1;i<=m;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            addE(u,v);
        }
        for(int i=1;i<=n;i++)
            if(dfn[i]==-1) tarjan(i);
        for(int i=1;i<=n;i++) {
            for(int j=head[i];j!=-1;j=e[j].nt)
                if(col[e[j].to]!=col[i])
                    du[col[i]]++;// 计算出度
            cnt[col[i]]++;
        }
        int tmp=0, ans;
        for(int i=1;i<=id;i++)
            if(du[i]==0) tmp++, ans=cnt[i];
        if(tmp==1) printf("%d\n",ans);
        else printf("0\n");
    }

    return 0;
}

原文地址:https://www.cnblogs.com/zquzjx/p/10011531.html

时间: 2024-10-12 15:41:54

USACO 2003 Fall Orange Popular Cows /// tarjan缩点 oj22833的相关文章

POJ 2186 Popular Cows -- tarjan 缩点

链接: POJ 2186 Popular Cows 题意: 每一头牛都希望在牛群里面备受瞩目,在一个牛群中有N头牛(1<=N<=10000),你被给予M(1<=M<=50000)个关系对,形式如(A,B),这意味着A牛认为B牛比它更受欢迎,由于这种欢迎度是满足传递性的,那么若是A牛认为B牛更受欢迎,B牛认为C牛更受欢迎,那么A牛也会认为C牛更受欢迎.你的任务是计算出被所有牛受欢迎的牛的个数. 输入: 第一行两个整数 N 和 M 第2 到 M + 1 行,两个分开的数 A,B,意味着

POJ2186 Popular Cows [tarjan 缩点]

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31241   Accepted: 12691 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 &

POJ 2186 Popular Cows tarjan缩点算法

题意:给出一个有向图代表牛和牛喜欢的关系,且喜欢关系具有传递性,求出能被所有牛喜欢的牛的总数(除了它自己以外的牛,或者它很自恋). 思路:这个的难处在于这是一个有环的图,对此我们可以使用tarjan算法求出强连通分量,把强连通分量压缩成一个点,构成一个新的图,这个图一定是没有环的,如果有环就跟强连通分量的矛盾了.压缩成无环图以后这个图里面的点是不具有方向的,我们通过遍历每个节点所能连到的点,如果两点的id值即所在的强连通分量区域不同时,我们就把这个节点的出度加1.最后去找那些出度等于0的点,如果

USACO 2003 Fall Orange Cow Exhibition /// 负数01背包 oj22829

题目大意: 输入n 接下来n行 每行输入 a b 输出n行中 a+b总和最大的同时满足 所有a总和>=0所有b总和>=0的值 负数的01背包应该反过来 w[i]为正数时 需要从大往小推 即往0推 w[i]为负数时 同样应该往0推 即与正数反过来 #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; int s[105],f[105],dp[1000*100*2+5]; int main() { in

Poj 2186 Popular Cows (Tarjan)

题目链接: Poj 2186 Popular Cows 题目描述: 有n只牛,牛之间存在一些关系,比如a认为b很受欢迎,b认为c很受欢迎,这样呢,a也会认为c很受欢迎,问根据给出的关系,有多少头牛被其他所有的牛都认为是受欢迎的? 解题思路: 对于一个有向无环图来说,其中有且仅有一个点出度为零,那么这个特殊的点,可以由其他任何点到达.那么接下来我们直接对所给的图进行强连通分量划分,然后把每个强连通分量看做一个点,判定出度为零的点有几个,如果有一个就输出这个点对应的强连通分量含有的节点个数,否则为零

Poj 2186 Popular Cows(Tarjan 强连通缩点)

传送门:Poj 2186 题意:给你n头牛,m种关系,A牛认为B牛是popular的,B牛认为C牛是popular的,则A也认为C是popular的,问最终有几头被所有牛认为是popular的牛 题解:强连通缩点基础题(虽然我Tarjan和缩点都是对的,但是最终讨论判断的时候写垮了(写了3天....还不是你懒!!!!过年划水这么多天缩点后找出度为零的点个数.然后讨论是否有这样子的点,如果没有则全都是(整个都是强连通图),如果只有一个,那么那个强连通分量所含的牛的个数就是所求解,如果有多个那么都是

poj2186Popular Cows tarjan缩点

//n个奶牛, //A B 表示A认为B出名,而且其有传递性 //如A认为B出名,B认为C出名,那么A认为C出名 //问有多少头奶牛所有的奶牛都认为其出名 //先对这个图缩点,记录每一个缩点的个数,然后找出度为0有且只有一个点 //如果是,那么那个点缩了几个点就是答案 #include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std ; con

poj 2186 Popular Cows 强连通缩点

[题意]:给出一群牛中,一头牛认为另一头牛受欢迎的m对关系,关系式可以传递的,即若a认为b受欢迎,b认为c受欢迎,那么a也认为c受欢迎.求最多有多少头牛被所有的牛认为受欢迎. [思路]:把这些关系形成的强连通图缩成点,就形成了一有向无环图,这个图里的出度为0的点(有且只有一个)就是被所有牛认为受欢迎的点,说明若这个点原来是强连通图就要求出这个强连通图里的总点数, 1 #include<iostream> 2 #include<stdio.h> 3 #include<strin

POJ2186 Popular Cows

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 <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popula