标签:mic ret span mes 增加 == nbsp do while 规模
★★ 输入文件:messagew.in
输出文件:messagew.out
简单对比
时间限制:1 s 内存限制:128 MB
这一道题其实还是比较简单的 就是一个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
标签:mic ret span mes 增加 == nbsp do while 规模
原文地址:https://www.cnblogs.com/Tidoblogs/p/11329587.html