信息传递--NOIP2015 day1 T2--暴力

这道题我用了判联通量加暴力,但联通量判炸了。。。。然后从code[VS]上看到个不错的代码,就拿来了^_^...

基本思路是去掉环外的点,然后走每一个联通块。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 
 7 int n,fa[200001],x[200001],ru[200001],g[200001];
 8 bool w[200001];
 9 //fa记录当前节点的传递目标,x记录每个环中每个点的长度
10 //ru记录每个点的入度,g记录每个环中的最终长度 
11 
12 
13 //快速读入
14 int getint()             
15 {
16     int w=0,q=0;
17     char c=getchar();
18     while ((c>'9'||c<'0')&&c!='-')        
19         c=getchar();
20     if (c=='-') q=1,c=getchar();
21     while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
22     return q?-w:w;
23 }
24 
25 //删除当前点,如果他的下一个点也只有一个入度,那么递归删除 
26 void shan(int k)
27 {
28     w[k]=1;
29     ru[fa[k]]--;
30     if(ru[fa[k]]==0)
31         shan(fa[k]);
32 }
33 
34 int main()
35 {
36     n=getint();
37     for (int i=1; i<=n; i++)
38         fa[i]=getint(),ru[fa[i]]++;        //读入 
39     
40     for (int i=1; i<=n; i++)
41         if(ru[i]==0&&!w[i])        //如果当前点只有一个入度 
42             shan(i);        //调用删除程序 
43             
44     for (int i=1; i<=n; i++)
45         if(!w[i])        //如果i没被删除 
46         {
47             x[1]=fa[i];
48             int y=fa[i],ans=1;
49             while (i!=y)                 //当环没有找到终点时 
50                 w[y]=1,y=fa[y],x[++ans]=y;        //递推 
51             for (int j=1; j<=ans; j++)
52                 g[x[j]]=ans;  //用g[最后一个点]记录最后的距离 
53         }
54     
55     int ans=0x7fffffff;
56     for (int i=1;i<=n;i++)
57         if(!w[i])        //如果m未被删除 
58             ans=min(ans,g[i]);        //取最小值 
59     printf("%d",ans);
60 }

 附DFS一个

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

const int MAXN = 200005;

int n;
int fa[MAXN];
int dfn[MAXN];
int vis[MAXN], vi = 0;;
int ans = 0x3f3f3f3f;
void dfs(int x, int df) {

     vis[x] = vi;
     dfn[x] = df;
     int nex = fa[x];

     if (!vis[nex]) dfs(nex, df + 1);
     else if (vis[nex] && vis[nex] != vi) return;
     else if (vis[nex] == vi) {
          ans = min(ans, df - dfn[nex] + 1);
          return;
     }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &fa[i]);
    }
    for (int i = 1; i <= n; i++) {
        if (!vis[i]) {
           vi++;
           dfs(i, 1);
        }
    }
    cout << ans << endl;
    return 0;   
}

 

posted @ 2016-01-05 21:40  OI_songer  阅读(427)  评论(0编辑  收藏  举报