码迷,mamicode.com
首页 > 编程语言 > 详细

河南2014 省赛 世界之威 拓扑排序

时间:2015-04-26 09:19:00      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:拓扑排序      

10404: E.世界之威

Time Limit: 2 Sec  Memory Limit: 128 MB
Submit: 2  Solved: 1
[Submit][Status][Web Board]

Description

某帝国拥有着N 种被称作“世界之威”的新型武器。现在为了国家的经济发展,它需要很多资金,为此,此帝国总统OBM准备把一些武器卖给其它国家。

此帝国总统OBM知道,N种武器之间可能会相互受限制的。例如,第3种武器会打败第1种武器,第4种武器会打败第3种武器等等。他希望所有被卖出的武器中都至少有一种限制它的武器在他手中,目的是此帝国能制约住其它国家,这样就可以保持对世界的霸权地位。

但总统OBM头脑有点笨,他想知道他最多可以卖出多少种武器,你愿意帮助他吗?

你可以告诉电脑,但不告诉他喽。

Input

第一行: K                           表示有多少组测试数据。

接下来对每组测试数据:

1:       N                表示有多少种新型武

2~N+1行: A1  A2……AN     表示i 种武器能限制住第Ai 种武器

  1≤K≤10   0≤N≤106    1≤Ai≤N  

Output

对于每组测试数据,输出占一行:最多可以卖出的武器种类数

Sample Input

172 3 1 3 6 5 4

Sample Output

3

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#define INF 100000000

using namespace std;

int a[100005],d[100005],vis[100005];



int main(){
	int t;
	cin >> t;
	while(t --){
		int n;
		scanf("%d",&n);
		priority_queue<int,vector<int>,greater<int> > que;
		memset(d,0,sizeof(d));
		memset(vis,0,sizeof(vis));
		int ans = 0,num = 0;
		for(int i = 1;i <= n;i++){
			scanf("%d",&a[i]);
			if(a[i] == i){
				num++;
			}
			d[a[i]] ++;
		} 		
		
		for(int i = 1;i <= n;i++){
			if(d[i] == 0){
				que.push(i);	
			}
		}
		
		
		while(!que.empty()){
			int p = que.top();
			que.pop();
			ans += 1;
			vis[p] = 1;
			
			if(vis[a[p]]){
				num += 1;
				continue;
			}
				
			d[a[a[p]]] --;
			vis[a[p]] = 1;
			if(d[a[a[p]]] == 0){
				que.push(p);
			}
			num += 2;
		}
		ans += (n-num) / 2;
		printf("%d\n",ans);
	} 
	return 0;
}


河南2014 省赛 世界之威 拓扑排序

标签:拓扑排序      

原文地址:http://blog.csdn.net/qq_24667639/article/details/45278513

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!