POI SZP

贪心:

初始所有点为白色,对于点i,若a[i]为白色则将其染成与i不同的颜色。

证明:若点i确定为白色,a[i]染白色也只能提供一个黑点,故a[i]染黑色不会差;若所有指向i的点均为黑色,则i只能是白色。

使用拓扑排序实现,一开始将无入度的点入队,最后剩下的环从任意处切开即可。

环上的情况可以分环为奇数,偶数通过讨论得到个数是对的。

SAC大佬%%%orz,提供链接:http://www.cnblogs.com/NaVi-Awson/

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 queue<int>Q;
 8 int n,m;
 9 int dist[1000001],a[1000001],ans=0;
10 bool vis[1000001],c[1000001];
11 int in[1000001];
12 int main()
13 {int i,j;
14 //freopen("szp.in","r",stdin);
15 //freopen("szp.out","w",stdout);
16     cin>>n;
17     for (i=1;i<=n;i++)
18     {
19         scanf("%d",&a[i]);
20         in[a[i]]++;
21     }
22       for (i=1;i<=n;i++)
23       if (!in[i]) Q.push(i);
24      while (!Q.empty())
25      {
26         int u=Q.front();
27           Q.pop();
28           vis[u]=1;
29            if (c[u])
30            {
31              in[a[u]]--;
32               if (!c[a[u]]) Q.push(a[u]);
33            }    
34            else
35            {
36               if (!c[a[u]]) ans++,c[a[u]]=1,Q.push(a[u]); 
37            }
38      }
39      for (i=1;i<=n;i++)
40       if (!vis[i])
41       {
42             vis[i]=1;
43             j=i;
44              while (!vis[a[j]])
45              {
46               if (!c[a[j]]&&!c[j]) ans++,c[a[j]]=1;
47               j=a[j];vis[j]=1;
48             }
49       }
50     cout<<ans;
51 }

 

posted @ 2017-08-24 15:43  Z-Y-Y-S  阅读(214)  评论(0编辑  收藏  举报