sicily 1350. Piggy banks

#include<iostream>        //给出每个点入度为1的有向图,求环的个数
#include<stdio.h>
using namespace std;
#define M 1000005
int par[M],vis[M],path[M],circle[M];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;++i)
scanf(
"%d",&par[i]);
for(int i=1;i<=n;++i)
{
vis[i]
=0;
circle[i]
=0;
}
int sum=0;
for(int i=1;i<=n;++i)
{
if(vis[i]==1)
continue;
int p=i,r=0;
while(vis[p]==0)
{
vis[p]
=1;
path[r
++]=p; //记录环的顶点
p=par[p];
}
if(circle[p]==0) //发现一个新的环
sum++;
for(int j=0;j<r;++j)
circle[path[j]]
=1; //标记已发现的环的顶点为1
}
printf(
"%d\n",sum);
}
return 0;
}

/*

题意:有N个存钱罐,标号为1~N,每个存钱罐的钥匙都放在某一个存钱罐当中。
要打开存钱罐,可以用钥匙开或者打烂存钱罐。问要打开所有的存钱罐,至少要打烂多少个存钱罐。

分析样例:n=4, 2 1 2 4, 意思是罐 2 的钥匙放在罐 1 里, 罐 1 的钥匙放在罐 2 里, 罐 3 的钥匙放在罐 2 里,罐 4 的钥匙放在罐 4 里
各有向边: 1->2 ,2->1 , 2->3, 4->4 有向边 s->t 的意思是罐 t 的钥匙放在罐 s 里,要打开罐 t 得先打开 罐 s ,所以 par[t]=s
故par[2]=1,par[1]=2,par[3]=2,par[4]=4 ,每个顶点的入度只能为 1 ,即它的父亲结点唯一,(你无法把钥匙同时放在两个罐子里)
可以看出,每个顶点的状态只能有2种: 自己 或者 它的父亲(祖先)结点 落在环内
所以问要打开所有的存钱罐至少得打烂多少个存钱罐,就相当于求图内存在多少个独立的环
如果一个顶点的父亲(祖先)结点落在环内,那么它也算做是环的一部分而不必另外计数

*/

  

posted on 2011-07-16 20:36  sysu_mjc  阅读(221)  评论(0编辑  收藏  举报

导航