• 洛谷P2341受欢迎的牛


    ####传送门啦

    这是一个tarjan强连通分量与出度结合的例题。

    先明确一下题意,如果这个点(缩点之后的)没有出度,这个点才能成为明星牛(明星牛的定义是:所有牛都喜欢他才可以)。

    由于我们进行了缩点,所以我就另外开一个数组num[i]:表示这个强连通分量中有多少个点。

    	int sum = 0;
    	for(int i=1;i<=cnt;i++)
    	  if(!chu[i])  ans = num[i] , sum++;
    	if(sum >= 2)  printf("0");
    	else printf("%d",ans);
    

    以上就是怎样处理最后的答案:

    如果我们有两个或以上出度为 0 点(缩点后的),说明这几个出度为 0 的点(缩点后)互相不喜欢,所以没有明星牛。

    否则就有明星牛(明星牛的个数就是出度为 0 的那个强连通分量中点的个数),很好想吧:那个强连通分量中的牛互相喜欢,而其他强连通分量中的牛也喜欢他们,等量代换所有牛都喜欢他

    首先是tarjan缩点中的几个数组:

     dfn[i]:i点的时间戳
    
     low[i],表示这个点以及其子孙节点连的所有点中dfn最小的值
    
     stack[],表示当前所有可能能构成是强连通分量的点。
    
     ins[i],表示 i 是否在stack[ ]数组中
    
     num[i],表示第 i 个强连通分量中有多少个点
    
     belong[i],表示第 i 点在哪一个强连通分量里
     
    

    下面就是AC代码了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e4 + 4;
    const int maxm = 5e4 + 4;
    
    int n,m,u,v;
    int head[maxn],tot;
    int dfn[maxn],low[maxn],ind;
    int stack[maxn],top,num[maxn],belong[maxn],cnt;
    bool ins[maxn];
    int chu[maxn],ans;
    struct Edge{
    	int from,to,next;
    }edge[maxm];
    
    void add(int u,int v){
    	edge[++tot].from = u;
    	edge[tot].to = v;
    	edge[tot].next = head[u];
    	head[u] = tot;
    }
    
    int read(){
    	char ch = getchar();
    	int f = 1 , x = 0;
    	while(ch > '9' || ch < '0'){
    		if(ch == '-')  f = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9'){
    		x = x * 10 + ch - '0';
    		ch = getchar(); 
    	}
    	return x * f;
    }
    
    void tarjan(int x){
    	dfn[x] = low[x] = ++ind;
    	stack[++top] = x;
    	ins[x] = true;
    	for(int i=head[x];i;i=edge[i].next){
    		int v = edge[i].to;
    		if(ins[v]) low[x] = min(low[x] , dfn[v]);
    		if(!dfn[v]){
    			tarjan(v);
    			low[x] = min(low[x] , low[v]);
    		}
    	}
    	int k = 0;
    	if(dfn[x] == low[x]){
    		cnt++;
    		do{
    			k = stack[top];
    			num[cnt]++;
    			top--;
    			ins[k] = false;
    			belong[k] = cnt;
    		} while(k != x);
    	}
    } 
    
    int main(){
    	n = read();  m = read();
    	for(int i=1;i<=m;i++){
    		u = read();  v = read();
    		add(u , v);
    	}
    	for(int i=1;i<=n;i++)
    	  if(!dfn[i])  tarjan(i);
    	for(int i=1;i<=m;i++){
    		if(belong[edge[i].from] != belong[edge[i].to]){
    			chu[belong[edge[i].from]]++;
    		}
    	}
    	int sum = 0;
    	for(int i=1;i<=cnt;i++)
    	  if(!chu[i])  ans = num[i] , sum++;
    	if(sum >= 2)  printf("0");
    	else printf("%d",ans);
    	return 0;
    }
    
    顺风不浪,逆风不怂。
  • 相关阅读:
    Symmetrical Network Acceleration with EBS 12
    Using Oracle Database In-Memory with Oracle E-Business Suite
    OI回忆录
    一只退役狗最后的想法
    codeforces-102501J Counting Trees题解
    CCPC2020 秦皇岛 H Holy Sequence
    CodeForces
    2020 ccpc 网络赛 1004 Chess Class
    2020 ccpc 网络赛 1012 Xor
    2020 ccpc 网络赛 1013 Residual Polynomial
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9884646.html
Copyright © 2020-2023  润新知