zoukankan      html  css  js  c++  java
  • [HAOI2006]受欢迎的牛

    1051: [HAOI2006]受欢迎的牛Time Limit: 10 Sec Memory Limit: 162 MB
    Submit: 7267 Solved: 3868
    [Submit][Status][Discuss]

    Description

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这

    种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头

    牛被所有的牛认为是受欢迎的。

    Input

      第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可

    能出现多个A,B)

    Output

      一个数,即有多少头牛被所有的牛认为是受欢迎的。

    Sample Input

    3 3
    1 2
    2 1
    2 3

    Sample Output

    1

    HINT

    100%的数据N<=10000,M<=50000

    solution

    不是一道很难的题,很容易看出来的是这个题首先就要Tarjan缩点,关键在于缩完点之后要怎么办,可以发现的是,如果这个图中有两个及以上出度为0的强连通分量,那么这个图里面就一定没有受欢迎的奶牛。那么直接记录图里出度为0的强连通分量是否多于一个就可以了。个数可以在跑Tarjan的时候记录。一开始Tarjan写错了居然找了半个小时

    Code

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    #define re register
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define MAXN 1000007
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    #define ms(arr) memset(arr, 0, sizeof(arr))
    const int inf = 0x3f3f3f3f;
    struct po
    {
        int nxt,to;
    };
    po edge[MAXN];
    int n,m,dfn[MAXN],low[MAXN],col[MAXN],stack[MAXN],vis[MAXN],tot[MAXN];
    int head[MAXN],num,color_num,s,tp,cnt,cd[MAXN],flag,ans;
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
        while(ch=='-') c*=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline void add_edge(int from,int to)
    {
        edge[++num].nxt=head[from];
        edge[num].to=to;
        head[from]=num;
    }
    inline void Tarjan(int u)
    {
        dfn[u]=++cnt;
        low[u]=cnt;
        vis[u]=1;
        stack[++tp]=u;
        for(re int i=head[u];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[v],low[u]);
            } else if(vis[v]) low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            color_num++;
            col[u]=color_num;
            tot[color_num]++;
            vis[u]=0;
            while(stack[tp]!=u){
                col[stack[tp]]=color_num;
                tot[color_num]++;
                vis[stack[tp--]]=0;
            }
            tp--;
        }
    }
    
    int main() 
    {
        //freopen("date.in","r",stdin);
        n=read();m=read();
        for(re int i=1;i<=m;i++){
        	int x=read(),y=read();
        	add_edge(x,y);
        }
        for(re int i=1;i<=n;i++)
        	if(!dfn[i]) Tarjan(i);
        for(re int i=1;i<=n;i++){
        	for(re int j=head[i];j;j=edge[j].nxt){
        		int v=edge[j].to;
        		if(col[v]!=col[i]) cd[col[i]]++;
        	}
        }
        for(re int i=1;i<=color_num;i++){
        	if(cd[i]==0) ans=i,flag++;
        	if(flag>1){
        		cout<<"0";
        		return 0;
        	}
        }
        cout<<tot[ans];
        return 0;
    }
    
  • 相关阅读:
    Week03-面向对象入门
    Week02-Java基本语法与类库
    201621123056 《Java程序设计》第1周学习总结
    2.2确定一个字符是否在指定范围内
    2.1确定一个char包含何种字符
    1.自己写一个计算器demo
    1.23 确定一个Decimal或Double的整数部分
    1.5 测试奇偶性
    1.2度转化为弧度 1.3弧度转换为度
    1.1确定分数与浮点数值之间的近似相等性。
  • 原文地址:https://www.cnblogs.com/victorique/p/8932619.html
Copyright © 2011-2022 走看看