zoukankan      html  css  js  c++  java
  • 【BZOJ】1051: [HAOI2006]受欢迎的牛(tarjan)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1051

    这题还好~1A了。。但是前提还是看了题解的 囧。。。。。一开始认为是并查集,oh,不行,,无法维护和判断。。好吧。

    看了题解后发现这是如何巧妙0v0!,我们将题目抽象为图,然后找出所有的环,你想啊,,,所有的换最后都有一条路径连向某一个环~那么恭喜这个环成为所有人的喜爱~~咳咳。。懂了吧。。判断这个最后的环用tarjan缩点后判断是否有且只有一个环没有连边出去,即出度为0,用前向星的就很好判断~~

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define read(a) a=getnum()
    #define print(a) printf("%d", a)
    inline int getnum() { int ret=0; char c; for(c=getchar(); c<'0' || c>'9'; c=getchar()); for(; c>='0' && c<='9'; c=getchar()) ret=ret*10+c-'0'; return ret; }
    
    const int N=10005, M=50005;
    int ihead[N], inext[M], to[M], cnt;
    int LL[N], FF[N], top, s[N], p[N], cyc, tot, vis[N], hav[N];
    int p_ihead[N], p_inext[M], p_cnt;
    int n, m, ans;
    
    inline void add(const int &u, const int &v) {
    	inext[++cnt]=ihead[u]; ihead[u]=cnt; to[cnt]=v;
    }
    
    void dfs(int u) {
    	s[++top]=u;
    	vis[u]=1;
    	LL[u]=FF[u]=++tot;
    	for(int i=ihead[u]; i; i=inext[i]) {
    		if(!FF[to[i]]) {
    			dfs(to[i]);
    			LL[u]=min(LL[u], LL[to[i]]);
    		}
    		else if(vis[to[i]] && FF[to[i]]<LL[u])
    			LL[u]=FF[to[i]];
    	}
    	if(LL[u]==FF[u]) {
    		++cyc;
    		int r;
    		do {
    			r=s[top--];
    			p[r]=cyc;
    			vis[r]=0;
    			++hav[cyc];
    		} while(r!=u);
    	}
    }
    
    void rebuild() {
    	for1(u, 1, n) {
    		for(int i=ihead[u]; i; i=inext[i]) {
    			if(p[u] != p[to[i]]) {
    				p_inext[++p_cnt]=p_ihead[p[u]];
    				p_ihead[p[u]]=p_cnt;
    			}
    		}
    	}
    }
    
    void tarjan() {
    	for1(i, 1, n) if(!FF[i]) dfs(i);
    	rebuild();
    }
    
    void getans() {
    	for1(i, 1, cyc) if(!p_ihead[i]) {
    		if(ans) { ans=0; return; }
    		else ans=hav[i];
    	}
    }
    
    int main() {
    	int x, y;
    	read(n); read(m);
    	for1(i, 0, n+1) p[i]=i;
    	rep(i, m) {
    		read(x); read(y);
    		add(x, y);
    	}
    	tarjan();
    	getans();
    	print(ans);
    	return 0;
    }
    

    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

    【数据范围】
    10%的数据N<=20, M<=50
    30%的数据N<=1000,M<=20000
    70%的数据N<=5000,M<=50000
    100%的数据N<=10000,M<=50000

    HINT

    Source

  • 相关阅读:
    2018最新程序员必备技术类微信公众号
    Navicat Premium for Mac 11.1.8 免费中文破解版下载
    尚硅谷Spring4视频教程免费下载
    业余草www.xttblog.com的最新文章推荐
    AdBlock — 最佳广告拦截工具(Chrome插件安利)
    Leetcode 705. 设计哈希集合【哈希表模板】
    Luogu P3370 【模板】字符串哈希
    POJ3737 UmBasketella
    POJ2456 Aggressive cows
    docker 离线安装
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3887624.html
Copyright © 2011-2022 走看看