# 样例1

## 样例输入1

5
2 4 2 3 1



## 样例输出1

3


【输入输出样例 1 说明】

# 来源

NOIP 2015 提高组 Day 1 第二题

1.bfs，如果一个点被访问了两次就说明有环，用第二次访问到该点的步数-第一次访问到该点的步数更新答案。

 1 #include<cstdio>
2 #include<algorithm>
3 #include<cmath>
4 #include<cstring>
5 #include<queue>
6
7 const int MAXN = 200002;
9 {
10     char ch = getchar(),c = ch;x = 0;
11     while(ch < '0' || ch > '9') c = ch,ch = getchar();
12     while(ch <= '9' && ch >= '0') x = (x<<1)+(x<<3)+ch-'0',ch = getchar();
13     if(c == '-') x = -x;
14 }
15
16 int n,t,cnt,ans;
18
19 struct Edge
20 {
21     int f,t,nxt;
22 }e[MAXN];
23
24 void insert(int f,int t)
25 {
26     e[++cnt].f = f,e[cnt].t = t;
29 }
30
31 inline int Min(int a,int b)
32 {return a<b?a:b;}
33
34 std::queue <int> q;
35
36 void bfs(int u)
37 {
38     memset(vis,0,sizeof(vis));
39     memset(step,0,sizeof(step));
40     q.push(u);
41     vis[u] = 1;
42     int tmp,v;
43     while(!q.empty())
44     {
45         tmp = q.front();
46         q.pop();
47         for(int i = head[tmp];i;i = e[i].nxt)
48         {
49             v = e[i].t;
50             if(vis[v]){
51                 ans = Min(ans,step[tmp]+1-step[v]);
52                 return;
53             }
54             vis[v] = 1;
55             step[v] = step[tmp]+1;
56             q.push(v);
57         }
58     }
59 }
60
61 int main()
62 {
64     for(int i = 1;i <= n;++ i)
65     {
67         insert(i,t);
68     }
69     ans = 2147483645;
70     for(int i = 1;i <= n;++ i)
71         if(!vis[i])
72             bfs(i);
73     printf("%d\n",ans);
74     return 0;
75 }
BFS 60'

2.tarjan缩点，答案即为元素数量最少但大于1的强连通分量的大小。

AC代码：

 1 #include<cstdio>
2 #include<algorithm>
3 #include<cmath>
4 #include<cstring>
5 #include<stack>
6
7 const int MAXN = 200002;
9 {
10     char ch = getchar(),c = ch;x = 0;
11     while(ch < '0' || ch > '9') c = ch,ch = getchar();
12     while(ch <= '9' && ch >= '0') x = (x<<1)+(x<<3)+ch-'0',ch = getchar();
13     if(c == '-') x = -x;
14 }
15
16 int n,t,cnt,dfn_cnt,part,ans;
18
19 struct Edge
20 {
21     int f,t,nxt;
22 }e[MAXN];
23
24 void insert(int f,int t)
25 {
26     e[++cnt].f = f,e[cnt].t = t;
29 }
30
31 inline int Min(int a,int b)
32 {return a<b?a:b;}
33
34 std::stack <int> s;
35
36 void Tarjan(int u)
37 {
38     dfn[u] = low[u] = ++ dfn_cnt;
39     s.push(u);
40     for(int i = head[u];i;i = e[i].nxt)
41     {
42         int v = e[i].t;
43         if(!dfn[v])
44         {
45             Tarjan(v);
46             low[u] = Min(low[u],low[v]);
47         }
48         else if(!belong[v])
49             low[u] = Min(low[u],dfn[v]);
50     }
51     if(dfn[u] == low[u])
52     {
53         part ++;
54         while(!s.empty())
55         {
56             int tmp = s.top();
57             s.pop();
58             belong[tmp] = part;
59             sum[part] ++;
60             if(tmp == u) break;
61         }
62     }
63 }
64
65 int main()
66 {
68     for(int i = 1;i <= n;++ i)
69     {
71         insert(i,t);
72     }
73     for(int i = 1;i <= n;++ i)
74         if(!dfn[i])
75             Tarjan(i);
76     ans = 2147483645;
77     for(int i = 1;i <= part;++ i)
78         if(sum[i] > 1 && sum[i] < ans)
79             ans = sum[i];
80     printf("%d\n",ans);
81     return 0;
82 }

posted @ 2017-10-26 16:32 超时空灰狼菌 阅读(...) 评论(...) 编辑 收藏