FZU Problem 2169 shadow

http://acm.fzu.edu.cn/problem.php?pid=2169

题目大意:

S王国有N个城市,有N-1条道路。王都为编号1的城市。叛军驻扎在许多城市。除了王都外有K个城市有军队,这K支军队要向王都进军,并且消灭沿途经过的城市中的叛军。每支军队只能沿着道路走,并且是其所在城市与王都之间的最短路线走。问能够消灭多少叛军?

思路:

有两种方法。

注意到题目只有N-1条边。是一颗树。

我想到的是对编号为1的结点(也就是王都,作为跟结点)进行DFS,一直遍历到树叶为止。沿途若发现有军队的,则往上传递可消灭叛军的信息。详见代码。

A了之后看了看别人的思路有方法二:

是对每个有军队的城市进行SPFA。每次消灭一次叛军就把叛军消除(Num置为0) 直到没有叛军或者全部军队遍历完。

但我总觉得怪怪的,军队向王都经过最短路径,但是方向不一定对啊!

如下面这组数据:

11 1

0 0 0 0 0 3 4 0 5 0 0

5

1 2

2 3

2 4

3 5

5 6

5 7

7 8

8 9

8 10

9 11

SPFA的结果为12.而DFS的为0.

按我对题目的理解也是0.

两个代码均AC。题目含糊。。

方法一:DFS

#include<cstdio>
#include<cstring>
const int MAXN=100000+10;
const int INF=0x3ffffff;
int head[MAXN],len,n,k,ans;
int num[MAXN];
bool vis[MAXN], army[MAXN];
struct edge
{
	int to,next;
}e[MAXN<<1];

void add(int from,int to)
{
	e[len].to=to;
	e[len].next=head[from];
	head[from]=len++;
}

bool dfs(int cur)
{
	for(int i=head[cur];i!=-1;i=e[i].next)
	{
		int id=e[i].to;
		if(vis[id])
			continue;
		vis[id]=true;
		if(dfs(id))
		{
			if(num[id]!=0)
				ans+=num[id];
			return true;
		}
		if(army[id] ==true)  //有军队
			return true;
	}
	return false;
}

int main()
{
	while(~scanf("%d%d",&n,&k))
	{
		int cnt=0;
		memset(head,-1,sizeof(head));
		memset(vis,0,sizeof(vis));
		len=0;

		for(int i=1;i<=n;i++)
		{
			scanf("%d",&num[i]);
			if(num[i])
				cnt++;
		}

		for(int i=0;i<k;i++)
		{
			int temp;
			scanf("%d",&temp);
			army[temp]=true;
		}

		for(int i=1;i<n;i++)
		{
			int from,to;
			scanf("%d%d",&from,&to);
			add(from,to);
			add(to,from);
		}
		ans=0;
		dfs(1);
		printf("%d\n",ans);
	}
	return 0;
}

方法二:SPFA

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=100000+10;
const int INF=0x3ffffff;
int head[MAXN],len,n,k;
int num[MAXN], army[MAXN];
int dis[MAXN];
bool vis[MAXN];
struct edge
{
	int to,next;
}e[MAXN<<1];

void add(int from,int to)
{
	e[len].to=to;
	e[len].next=head[from];
	head[from]=len++;
}

void spfa(int s)
{
	queue<int> q;
	for(int i=1;i<=n;i++)
	{
		dis[i]=INF;
		vis[i]=false;
	}
	q.push(s);
	dis[s]=0;
	while(!q.empty())
	{
		int cur=q.front();
		q.pop();
		vis[cur]=false;
		for(int i=head[cur];i!=-1;i=e[i].next)
		{
			int id=e[i].to;
			if(dis[id] > dis[cur] + 1)
			{
				dis[id]=dis[cur]+1;
				if(!vis[id])
				{
					q.push(id);
					vis[id]=true;
				}
			}
		}
	}
}

int main()
{
	while(~scanf("%d%d",&n,&k))
	{
		int cnt=0;
		memset(head,-1,sizeof(head));
		len=0;

		for(int i=1;i<=n;i++)
		{
			scanf("%d",&num[i]);
			if(num[i])
				cnt++;
		}

		for(int i=0;i<k;i++)
			scanf("%d",&army[i]);

		for(int i=1;i<n;i++)
		{
			int from,to;
			scanf("%d%d",&from,&to);
			add(from,to);
			add(to,from);
		}
		int ans=0;
		for(int i=0;i<k;i++)
		{
			spfa(army[i]);

			for(int j=1;j<=n;j++)
			{
				if(!num[j] || dis[j]==INF) //不能到达或者没有叛军
					continue;
				ans+=num[j];
				num[j]=0;
				cnt--;
				if(cnt==0)
					goto next;
			}
		}
next:
		printf("%d\n",ans);
	}
	return 0;
}

FZU Problem 2169 shadow

时间: 2024-12-16 10:56:35

FZU Problem 2169 shadow的相关文章

Problem 2169 shadow

 Problem 2169 shadow Accept: 141    Submit: 421 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description YL是shadow国的国王,shadow国有N个城市. 为了节省开支,shadow国仅仅有N-1条道路,这N-1条道路使得N个城市连通.某一年,shadow国发生了叛乱,叛军占据了多个城市,王都岌岌可危. 王都为编号为1的城市,除了王都外有K个城市有YL的军队.如

福州大学 Problem 2169 shadow

http://acm.fzu.edu.cn/problem.php?pid=2169 思路:建立一个邻接表,利用搜索中回溯把走过的路标记为1,然后把这些标记为1的值全部加起来. Problem 2169 shadow Accept: 97    Submit: 274 Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description YL是shadow国的国王,shadow国有N个城市.为了节省开支,shadow国只有N-1

FZU_Problem 2169 shadow

Problem 2169 shadow Accept: 173 Submit: 553 Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description YL是shadow国的国王,shadow国有N个城市.为了节省开支,shadow国只有N-1条道路,这N-1条道路使得N个城市连通.某一年,shadow国发生了叛乱,叛军占领了多个城市,王都岌岌可危.王都为编号为1的城市,除了王都外有K个城市有YL的军队.现在这K支军队要向王都进

FZU Problem 2171 防守阵地 II (线段树,区间更新)

 Problem 2171 防守阵地 II Accept: 143    Submit: 565Time Limit: 3000 mSec    Memory Limit : 32768 KB  Problem Description 部队中总共有N个士兵,每个士兵有各自的能力指数Xi,在一次演练中,指挥部确定了M个需要防守的地点,指挥部将选择M个士兵依次进入指定地点进行防守任务,获得的参考指数即为M个士兵的能力之和.随着时间的推移,指挥部将下达Q个指令来替换M个进行防守的士兵们,每个参加完防守

FZU Problem 2034 Password table (简单模拟题)

这种简单题做了好长时间,我是不是有点逗? 地址:http://acm.fzu.edu.cn/problem.php?pid=2034 不解释了,自己看吧,练手的好题 上个代码吧 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <stdio.h> #include <string.h> #include <stdlib.h>

FZU Problem 2238 Daxia &amp; Wzc&#39;s problem

Daxia在2016年5月期间去瑞士度蜜月,顺便拜访了Wzc,Wzc给他出了一个问题: Wzc给Daxia等差数列A(0),告诉Daxia首项a和公差d; 首先让Daxia求出数列A(0)前n项和,得到新数列A(1); 然后让Daxia求出数列A(1)前n项和,得到新数列A(2); 接着让Daxia求出数列A(2)前n项和,得到新数列A(3); 规律题,首先写出 a.a+d.a+2d.a+3d...这个容易写出 下面一行也容易写出:a.2a+d.3a+3d.... 再下一行,确实难写,但是通过上

FZU Problem 2168 防守阵地 I

http://acm.fzu.edu.cn/problem.php?pid=2168 题目大意: 给定n个数和m,要求从n个数中选择连续的m个,使得a[i]*1+a[i+1]*2+--a[i+m]*m最大 思路: 常规思路是以每个数开始,枚举m个,但是这样会TLE. 可以有O(n)的算法. 例如样例的 n=5 m=3 五个数分别为 2 1 3 1 4 有三种连续的三个数 2 * 1 + 1 * 2 + 3* 3 = 13 1 * 1 + 3 * 2 + 1 * 3= 10 3 * 1 + 1 *

FZU Problem 2062 Suneast &amp; Yayamao

http://acm.fzu.edu.cn/problem.php?pid=2062 题目大意: 给你一个数n,要求求出用多少个数字可以表示1~n的所有数. 思路: 分解为二进制. 对于一个数n,看它二进制有多少位即可. #include<cstdio> int main() { int n; while(~scanf("%d",&n)) { int k=0; while(n) { n>>=1; k++; } printf("%d\n"

FZu Problem 2233 ~APTX4869 (并查集 + sort)

题目链接: FZu Problem 2233 ~APTX4869 题目描述: 给一个n*n的矩阵,(i, j)表示第 i 种材料 和 第 j 种材料的影响值,这个矩阵代表这n个物品之间的影响值.当把这n个物品分成两部分后,每部分内部材料不会相互影响,但是不同部分的材料之间会相互影响.问如何分割使得两部分材料相互之间的最小影响值最大? 解题思路: 材料内部不会影响,那么只需要把影响值小的物品放在同一部分即可,所以用结构体保存物品之间的影响值,然后sort一下,影响值小的物品用并查集放在一个集合,当