zoukankan      html  css  js  c++  java
  • cogs 1001. [WZOI2011 S3] 消息传递 Tarjan

    1001. [WZOI2011 S3] 消息传递

    ★★   输入文件:messagew.in   输出文件:messagew.out   简单对比
    时间限制:1 s   内存限制:128 MB

    Problem 2 消息传递 (messagew.pas/c/cpp)
    问题描述
    WZland开办了一个俱乐部(这里面可以干任何的事情),这引来了许多的人来加入。俱乐部的人数越来越多,关系也越来越复杂……
    俱乐部的人来自各个地方,为了增加友谊,俱乐部举行了一次晚会。晚会上又进行了一个传话游戏,如果A认识B,那么A收到某个消息,就会把这个消息传给B,以及所有A认识的人(如果A认识B,B不一定认识A),所有人从1到N编号。
    现在给出所有“认识”关系,俱乐部的负责人WZland的国王想知道一个十分简单的问题:如果A发布一条新消息,那么会不会经过若干次传话后,这个消息传回给了A,1≤A≤N。但是WZland的国王是出了名的数学差,幸好的是你在他的身边,于是他就将这个问题交给你来解决。




    输入格式
    输入数据中的第一行是两个数N和M,两数之间有一个空格,表示人数和认识关系数。
    接下来的M行,每行两个数A和B,表示A认识B(1A, BN,AB)。
    输出格式
    输出文件中一共有N行,每行一个字符“T”或“F”。第i行如果是“T”,表示i发出一条新消息会传回给i;如果是“F”,表示i发出一条新消息不会传回给i。
    样例输入输出
    messagwe.in 
    4 6
    1 2
    2 3
    4 1
    3 1
    1 3
    2 3
    messagew.out
    T
    T
    T
    F




    数据规模
    对于30%的数据,N≤1000,M≤20000;
    对于50%的数据,N≤10000,M≤100000;
    对于100%的数据,N≤100000,M≤200000;
    认识关系可能会重复给出。
    时间限制
    1s

    这一道题其实还是比较简单的 就是一个Tarjan而已
    那么应该怎么进行处理呢??只要  当前点所在的强连通分量的大小>1 就相当于 这个点传出去以后 还能有人再给他传回来!else  就是他自己一个人 肯定不行啦

    至于那个认识关系可能会重复。。。我一开始也没有想到怎样处理 就闭着眼交了上去 居然A了 后来想明白了(还是板子高明啊)快看快看:

    那个第67行看到没  就是如果to点已经在栈中了  就把当前点的low 和 to点的dfn取一个较小的值 直接就返回了 不会出bug了

    (<<本人心声:清华orz的板子就是厉害!赞一个)

    下面来贴出简洁清晰(自认为)的代码吧

    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define maxn 100005
    using namespace std;
    int n,m;
    vector<int> v[maxn];
    int dfn[maxn],low[maxn],size[maxn],scc_cnt,st[maxn],cnt,tim,belong[maxn];
    bool bein[maxn];
    void Tarjan(int rt)
    {
        dfn[rt]=low[rt]=++tim;//时间戳++ 初始化dfn和low相等
        st[++cnt]=rt;//该点入栈
        bein[rt]=true; //标记是否在栈中的数组
        for(int i=0;i<v[rt].size();i++)
        {
            int to=v[rt][i];
            if(!dfn[to]) 
                Tarjan(to),low[rt]=min(low[rt],low[to]);
            else if(bein[to])
                low[rt]=min(low[rt],dfn[to]);
        }
        if(dfn[rt]==low[rt])
        {
            scc_cnt++;//统计强连通分量 
            int k;
            do{
                k=st[cnt];
                cnt--;
                belong[k]=scc_cnt;
                bein[k]=false;
                size[scc_cnt]++;
            }while(k^rt);//^ 在这里就相当于!=        do while  是先跑一遍再判断    
        }
    }
    int main()
    {
        freopen("messagew.in","r",stdin);
        freopen("messagew.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            v[x].push_back(y);//这里要注意是一条单项边啊 
        }    
        for(int i=1;i<=n;i++)
            if(!dfn[i])//如果未访问 
                Tarjan(i);
        for(int i=1;i<=n;i++)
        {
            if(size[belong[i]]>1)
                puts("T");
            else
                puts("F");
        }
        return 0;
    }
  • 相关阅读:
    浅析HTT
    html5移动端页面分辨率设置及相应字体大小设置的靠谱使用方式
    CSS--posiion学习日记
    面向对象程序设计课程感想
    OO第二单元(5-8周)作业总结
    OO第一作业周期(前四周)总结
    OO第三阶段作业总结
    OO第二单元作业总结
    Java学习第一阶段作业总结
    面向对象OO课程学习总结
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/11329587.html
Copyright © 2011-2022 走看看