cogs 1001. [WZOI2011 S3] 消息传递 Tarjan

Posted tidoblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;

 

以上是关于cogs 1001. [WZOI2011 S3] 消息传递 Tarjan的主要内容,如果未能解决你的问题,请参考以下文章

cojs 1001. [WZOI2011 S3] 消息传递

1002. [WZOI2011 S3] 周年纪念日

cogs 944. [東方S3] 藤原妹红

cogs 942. [東方S3] 比那名居天子

WZOI 磁暴题解

cogs 1901. [国家集训队2011]数颜色