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 }