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

    ——BZOJ1051

    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 $

    Analysis

    ​ 我们需要考虑哪些牛受欢迎,就是考虑哪些点能被所有点访问过。

    ​ 这道题我的思维过程是这样的:试想一下出度为0的点。如果整张图只有一个出度为0的点,那么它肯定是受欢迎的。(有两个就不是了,不能互相到达)

    ​ 那要是没有出度为0的点呢,那就是有环呗,环之间的点都能互相到达,那只要环外的点都能到达环,那环内的点都受欢迎。一个环就是强连通分量,那强连通分量里的点都能互相到达。那我们就想到了刚才说的结论,联想到把强联通分量想象成一个点,这个点可是出度为0的,若是只有一个这样的“点”的话,就有很多受欢迎的牛了。

    ​ 这就是强联通分量缩点的算法。强联通分量用tarjan来求,缩点重构图操作一下,答案就求出来了。

    code

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn = 100005;
    bool vis[maxn];
    int runn[maxn];
    vector <int> edge[maxn];
    vector <int> fedge[maxn];
    int m,n;
    int ans;
    int tot;
    int dfn[maxn],st[maxn],low[maxn],ins[maxn],bel[maxn],top,cnt,scc,buc[maxn],visb[maxn];
    void tarjan(int x)
    {
    	dfn[x] = low[x] = ++cnt;
    	st[++top] = x;
    	ins[x] = 1;
    	for(int i=0;i<edge[x].size();i++)
    	{
    		if(!dfn[edge[x][i]])
    		{
    			tarjan(edge[x][i]);
    			low[x] = min(low[x],low[edge[x][i]]);
    		}
    		else if(ins[edge[x][i]])
    			low[x] = min(low[x],dfn[edge[x][i]]);
    	}
    	if(dfn[x] == low[x])
    	{
    		int t;
    		ins[x] = 0;
    		bel[x] = ++scc;
    		while(st[top] != x)
    		{
    			t = st[top--];
    			ins[t] = 0;
    			bel[t] = scc;
    		}
    		top--;
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		edge[x].push_back(y);
    	}
    	for(int i=1;i<=n;i++)
    		if(!dfn[i])
    			tarjan(i);
    	for(int i=1;i<=n;i++)
    		buc[bel[i]]++;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<edge[i].size();j++)
    		{
    			if(bel[i] != bel[edge[i][j]])
    				fedge[bel[i]].push_back(bel[edge[i][j]]);
    		}
    	}
    	for(int i=1;i<=scc;i++)
    		if(!fedge[i].size())
    			ans += buc[i];
     	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    判断是否为蜘蛛抓取
    js Date
    JavaScript_Date对象说明
    php过滤字符串函数
    js 高考倒计时
    php 修改数据编码
    php 二维数组冒泡排序
    PSD网页切图制作HTML全过程教程
    产品经理职责
    互联网产品设计
  • 原文地址:https://www.cnblogs.com/Ch-someone/p/9521876.html
Copyright © 2011-2022 走看看