• 51Nod2849 信息传递


    Problem

    有n个同学(编号为 1 到 n )正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为 i 的同学的信息传递对象是编号为 Ti的同学。游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自己的生日时,游戏结束。请问该游戏一共可以进行几轮?

    Solution

    找出最小的环,由于每个人只会把信息告诉一个人,因此所有环都是无弦环(无弦环: 非相邻节点间不存在边的环),也就是说,每个强连通分量都只有一个环,找出最小的强连通分量(不为1)即可。

    代码根据题意在Tarjan基础上做了一些简化。

    Code

    #include<stdio.h>
    #include<iostream>
    #define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    using namespace std;
    #include<string>
    #include<stack>
    #include<map>
    #include<vector>
    const int MAXN=200020;
    const int MAXM=200020;
    int n,m,idx,cnt,mn=200020;
    int dfn[MAXN];
    int low[MAXN];
    bool instack[MAXN];
    int a[MAXN];
    struct E{
    	int u,v,nex;
    }e[MAXM];
    stack<int>s;
    void Tarjan(int u){
    	dfn[u]=low[u]=++idx;
    	s.push(u);
    	instack[u]=true;
    	int v=a[u];
    	if(!dfn[v]){
    		Tarjan(v);
    		low[u]=min(low[u],low[v]);
    	}
    	else if(instack[v]){
    		low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u]){
    		int cur,ct=0;
    		do{
    			cur=s.top();s.pop();
    			instack[cur]=false;
    			ct++;
    		}while(cur!=u);
    		if(ct>1) mn=min(mn,ct);
    	}
    }
    
    int main(){
    	io_opt;
    	cin>>n;
    	int x;
    	for(int i=1;i<=n;i++){
    		cin>>a[i];
    	}
    	for(int i=1;i<=n;i++){
    		if(!dfn[i]) Tarjan(i);
    	}
    	cout<<mn<<endl;
    	return 0;
    }
    
  • 相关阅读:
    JAVA BigDecimal 小数点处理
    对 Element UI table中数据进行二次处理
    Kettle-User Defined Java Class使用-大写转换
    多线程-同步函数
    多线程-银行分批存款
    多线程-并发卖票
    多线程-控制两个线程交替打印
    ztree-可拖拽可编辑的树
    ztree-编辑节点(树节点添加,删除,修改)
    ztree-拖拽(排序树)
  • 原文地址:https://www.cnblogs.com/sz-wcc/p/12614531.html
Copyright © 2020-2023  润新知