您的位置:首页 > 其它

【noip 2015】信息传递

2017-10-21 11:26 295 查看
去题面的传送门

QAQ这题有两种做法

Solution 1: 暴力找环

很明显题目是让找最小环,那我们就顺着找呗。一开始尝试用递归做,弄了半天也不行,不太好记录已经跑过了几个点。

其实每一个点的出度都是1,所以不用存图,直接一个数组记录每一个点连接的下一个节点是哪一个就行了。

记得还要for一遍,确定每一个点都跑过。

但是一开始这样交超时了。

后来发现,其实每次从一个点开始找环的时候,如果直接找到的下一个点是之前访问过的,直接return就好了

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn=200000+10;
int n,ans,tot;
int nxt[maxn],pre[maxn],cnt[maxn];

void done(int x)
{
int now=x,num=0;
while(true)
{
num++;
if(pre[now])
{
if(pre[now]==x) ans=min(ans,num-cnt[now]);
break;
}
cnt[now]=num;
if(!pre[now]) tot++;
pre[now]=x;
now=nxt[now];
}
}
int main()
{
scanf("%d",&n);
ans=2147483647;
for(int i=1;i<=n;++i) scanf("%d",&nxt[i]);
for(int i=1;i<=n;++i)
{
if(tot==n) break;
if(!pre[i]) done(i);
}
printf("%d",ans);
return 0;
}


Solution 2:tarjan找环

很简单,打了一遍没调就过了

直接上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;

const int maxn=200000+10;
int n,scc_cnt,Index,ans;
int nxt[maxn],scc[maxn],dfn[maxn],low[maxn];
vector<int>incom[maxn];
stack<int>s;

void tarjan(int i)
{
dfn[i]=low[i]=++Index;
s.push(i);
if(!dfn[nxt[i]])
{
tarjan(nxt[i]);
low[i]=min(low[i],low[nxt[i]]);
}
else if(!scc[nxt[i]]) low[i]=min(dfn[nxt[i]],low[i]);
if(low[i]==dfn[i])
{
scc_cnt++;
int j;
do
{
j=s.top();
s.pop();
incom[scc_cnt].push_back(j);
scc[j]=scc_cnt;
}
while(i!=j);
}
}
int main()
{
scanf("%d",&n);
ans=2147483647;
for(int i=1;i<=n;++i) scanf("%d",&nxt[i]);
for(int i=1;i<=n;++i)
if(!scc[i]) tarjan(i);
for(int i=1;i<=scc_cnt;++i)
{
int x=incom[i].size();
if(x>1)
ans=min(ans,x);
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: