• Luogu P2661 信息传递


    思路

    显然,所有的边都是有向边。那么一个人能够得到自己的生日的条件便是这个人在一个环中,而且要求的是最小环。那么我们就可以用Tarjan算法求解。不会Tarjan的人可以去看看我另一篇随笔,专门讲的Tarjan我脚地窝写的海星。想看的话可以点这里。还有就是要注意环的大小必须要超过1。。。。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <stack>
    
    const int maxn = 2e5+3;
    
    using namespace std;
    
    stack<int> S;
    int n, x, f, u[maxn], v[maxn], first[maxn], next[maxn], cnt;
    char c;
    bool vis[maxn];
    int low[maxn], dfn[maxn], Index, tot, ans = 2147483647;
    
    inline int readInt() {
    	x = 0, f = 1;
    	c = getchar();
    	while (c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while (c <= '9' && c >= '0') {
    		x = x*10 + c-'0';
    		c = getchar();
    	}
    	return x * f;
    }
    
    inline void Tarjan(int now) {
    	low[now] = dfn[now] = ++Index;
    	S.push(now);
    	vis[now] = 1;
    	int k = first[now];
    	while (k != -1) {
    		if(!dfn[v[k]]) {
    			Tarjan(v[k]);
    			low[now] = min(low[now], low[v[k]]);
    		}
    		else if(vis[v[k]] && dfn[v[k]]) {
    			low[now] = min(low[now], dfn[v[k]]);
    		}
    		k = next[k];
    	}
    	int temp, num = 0;
    	if(dfn[now] == low[now]) {
    		while(!S.empty()) {
    			temp = S.top();
    			S.pop();
    			num ++;
    			vis[temp] = 0;
    			if(temp == now) break;
    		}
    		if(num > 1) {
    			ans = min(ans, num);
    		}
    	}
    }
    
    int main() {
    	n = readInt();
    	memset(first, -1, sizeof(first));
    	for(int i=1; i<=n; i++) {
    		u[i] = i, v[i] = readInt();
    		next[i] = first[u[i]];
    		first[u[i]] = i;
    	}
    	for(int i=1; i<=n; i++) {
    		if(!dfn[i]) Tarjan(i);
    	}
    	printf("%d", ans);
    }
    

      

  • 相关阅读:
    C语言volatile关键字的用法
    UDP广播包
    进程和线程的区别
    Unix/Linux进程间通信
    虚拟空间,malloc
    自我介绍
    java初始化顺序
    java 队列基础操作
    java IO基础操作
    Python中的Tab补全功能添加
  • 原文地址:https://www.cnblogs.com/bljfy/p/9334307.html
Copyright © 2020-2023  润新知