Sicily 1350. Piggy banks (有向图求环)
题目:http://soj.me/1350
n个储蓄罐 储蓄罐的钥匙在储蓄罐内 已知钥匙所在的储蓄罐 求最少打破几个储蓄罐才能取出钱。
思路:
- 求图中环的个数
- 由于图中每个点的出度只有1,所以不存在一个点处于两个环的交点
- 因此,求环的个数时每个只需要考虑一次便可得出结果
- 由于数据规模庞大,写成递归形式容易暴栈
- 在读边的过程中先对自环进行预处理,之后对每个点进行不同的染色,对它的下一个点也染同样的颜色
- 这样染下去如果发现下一个要染的点和正在染的颜色相同,则说明存在一个环
- 换染色起点的同时也需要更换新的染色,才能保证对环的判断正确
又一次栽在多case的初始化上...
#include <iostream>
using namespace std; struct piggy { int key; int flag; struct piggy *next; }node[1000005]; int ans=0; int num=1; int n; void search() { struct piggy *p; for(int i=1;i<=n;i++) { if(node[i].flag!=-1) continue; p=&node[i]; while(1) { p->flag=num; if(p->next!=NULL) { if(p->next->flag==p->flag) { ans++;num++;break; } else if(p->next->flag!=-1) {num++;break;} else { p=p->next; } } else { num++;break; } } } } int main() { while( cin >> n ) { ans=0;num=1; for(int i=1;i<=n;i++) { int temp; cin>>temp; node[i].key=temp; node[i].flag=-1; node[i].next=&node[node[i].key]; if(i==node[i].key) { node[i].flag=0; ans++; num++; } } search(); cout<<ans<<endl; } return 0; }