zoukankan      html  css  js  c++  java
  • Luogu2341 受欢迎的牛

    好题。

    在有向图中找到强连通子图,缩点,记上里面有几头牛,变成DAG。

    然后找出出度为0的点。如果这样的点的数量不等于1显然输出0。否则答案就是这个点的原点数。

    为了方便,反向建边,变统计出度为入度。枚举每一个原图的点u,如果找到原图中与u点相连的v不属于同一个scc,那么入度+1。(即不重建图。

    打了四遍这个题真TM爽

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define maxn 10001
    #define maxm 50001
    using namespace std;
    int head[maxn];
    struct edge{
    	int to, nxt;
    }e[maxm];
    int n, m, tot, top, cnt, col;
    int dfn[maxn], st[maxn], low[maxn], scc[maxn];
    int sl[maxn], ind[maxn];
    void add(int u, int v){
    	e[++tot].nxt=head[u];
    	e[tot].to=v;
    	head[u]=tot;
    }
    void tarjan(int u){
    	dfn[u]=low[u]=++cnt;
    	st[++top]=u;
    	for(int i=head[u]; i; i=e[i].nxt){
    		int v=e[i].to;
    		if(!dfn[v]){
    			tarjan(v);
    			low[u]=min(low[u], low[v]);
    		}else if(!scc[v])
    			low[u]=min(low[u], dfn[v]);
    	}
    	if(low[u]==dfn[u]){
    		scc[u]=++col;
    		++sl[col];
    		while(st[top]!=u){
    			++sl[col];
    			scc[st[top]]=col;
    			top--;
    		}
    		top--;
    	}
    }
    int main(){
    	scanf("%d%d", &n, &m);
    	int x, y;
    	for(int i=1; i<=m; i++){
    		scanf("%d%d", &x, &y);
    		add(y,x);
    	}
    	for(int i=1; i<=n; i++)
    		if(!dfn[i]) tarjan(i);
    	for(int i=1; i<=n; i++)
    		for(int j=head[i]; j; j=e[j].nxt){
    			int v=e[j].to;
    			if(scc[i]!=scc[v])
    				ind[scc[v]]++;
    		}
    	int ans=0, indtj=0;
    	for(int i=1; i<=col; i++)
    		if(!ind[i])
    			ans=sl[i], indtj++;
    	if(indtj==1)
    		printf("%d", ans);
    	else printf("0");
    	return 0;
    }
    
  • 相关阅读:
    SQLServer和Access数据传输简单总结
    Session 详解
    SQL日志文件过大问题的解决方法
    如何删除表中的重复记录?
    HDOJ 3711 Binary Number
    HDOJ 2022
    活动选择问题
    浮点数的比较
    HDOJ 2037
    找最长递增子数列
  • 原文地址:https://www.cnblogs.com/pushinl/p/9911659.html
Copyright © 2011-2022 走看看