LightOJ 1219 Mafia(dfs—树上贪心)

1219 - Mafia
Time Limit: 1 second(s)Memory Limit: 32 MB

Don Seliari gives his right hand Tommas Angelo (Tommy) an important job to guard his territory. The mafia territory consists of n cities. And the cities are connected to each other in such a way that there is exactly one path from any city to another. Tommy has exactly n mafia boys to guard the cities. Initially the mafia boys are resting randomly at the n cities. Tommy wants every city to be guarded by the mafia boys. This is to be accomplished by a sequence of moves; each move consists of moving one mafia boy to the adjacent city. What is the minimum number of moves required so that every city is guarded?

Input

Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with a line containing an integer n (1 ≤ n ≤ 10000).Each of the next n line contains at least three numbers which are: v the number of a city, followed by the number of mafia boys placed at city v followed by a number d which is the number of cities adjacent of v, followed by d numbers giving the adjacent cities of v. Amongst the cities, one city is chosen as root, and for any city all its adjacent cities are listed except the one that connects it (through a path) to the root city.

Output

For each case, print the case number and the minimum number of moves required for the mafia boys to guard all cities.

Sample Input

Output for Sample Input

2

9

1 2 3 2 3 4

2 1 0

3 0 2 5 6

4 1 3 7 8 9

5 3 0

6 0 0

7 0 0

8 2 0

9 0 0

9

1 0 3 2 3 4

2 0 0

3 0 2 5 6

4 9 3 7 8 9

5 0 0

6 0 0

7 0 0

8 0 0

9 0 0

Case 1: 7

Case 2: 14

 


这道题也是磨了好几天,vector建的单向边各种炸,不多说了,贴一个邻接表的代码吧


代码如下:


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 10010
int val[maxn],mark[maxn],ans;
struct node
{
	int u,v,next;
}edge[maxn];
int head[maxn],top; 

void init()
{
	memset(head,-1,sizeof(head));
	top=0;
	memset(mark,0,sizeof(mark));
} 

void add(int u,int v)
{
	edge[top].v=v;
	edge[top].next=head[u];
	head[u]=top++;
}

void dfs(int u,int pre)
{
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		dfs(v,u);
	}
	ans+=abs(val[u]-1);
	val[pre]+=(val[u]-1);
}

int main()
{
	int t,n,m,u,v,k=1,i;
	scanf("%d",&t);
	while(t--)
	{
		init();
		scanf("%d",&n);
		for(i=0;i<n;++i)
		{
			scanf("%d",&u);
			scanf("%d%d",&val[u],&m);
			while(m--)
			{
				scanf("%d",&v);
				mark[v]++; 
				add(u,v);
			}
		}
		int root=-1;
		for(i=1;i<=n;++i)
		{
			if(!mark[i])
				root=i;
		}
		ans=0;
		dfs(root,-1);
		printf("Case %d: %d\n",k++,ans);
	}
	return 0;
} 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值