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



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的更多相关文章

  1. 福州大学 Problem 2169 shadow

    http://acm.fzu.edu.cn/problem.php?pid=2169 思路:建立一个邻接表,利用搜索中回溯把走过的路标记为1,然后把这些标记为1的值全部加起来. Problem 216 ...

  2. Problem 2169 shadow

     Problem 2169 shadow Accept: 141    Submit: 421 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Pr ...

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

    题目链接: FZu Problem 2233 ~APTX4869 题目描述: 给一个n*n的矩阵,(i, j)表示第 i 种材料 和 第 j 种材料的影响值,这个矩阵代表这n个物品之间的影响值.当把这 ...

  4. FZu Problem 2236 第十四个目标 (线段树 + dp)

    题目链接: FZu  Problem 2236 第十四个目标 题目描述: 给出一个n个数的序列,问这个序列内严格递增序列有多少个?不要求连续 解题思路: 又遇到了用线段树来优化dp的题目,线段树节点里 ...

  5. 翻翻棋(找规律问题)(FZU Problem 2230)

    题目是这样的: FZU Problem 2230 象棋翻翻棋(暗棋)中双方在4*8的格子中交战,有时候最后会只剩下帅和将.根据暗棋的规则,棋子只能上下左右移动,且相同的级别下,主动移动到地方棋子方将吃 ...

  6. FZU 2169 shadow (用了一次邻接表存边,树形DP)

    Accept: 28 Submit: 97 Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description YL是shadow国的国 ...

  7. FZU 2169 shadow spfa

    题目链接:shadow 好佩服自己耶~~~好厉害~~~ 麻麻再也不用担心我的spfa 和 邻接表技能了~~~ spfa 记录最短路径. #include <stdio.h> #includ ...

  8. fzu Problem 2148 Moon Game(几何 凸四多边形 叉积)

    题目:http://acm.fzu.edu.cn/problem.php?pid=2148 题意:给出n个点,判断可以组成多少个凸四边形. 思路: 因为n很小,所以直接暴力,判断是否为凸四边形的方法是 ...

  9. fzu Problem 2140 Forever 0.5(推理构造)

    题目:http://acm.fzu.edu.cn/problem.php?pid=2140 题意: 题目大意:给出n,要求找出n个点,满足: 1)任意两点间的距离不超过1: 2)每个点与(0,0)点的 ...

随机推荐

  1. Labview中引用,属性节点,局部变量之间的区别

    Labview中引用,属性节点,局部变量之间的区别        在Labview中我们经常会碰到这样几个概念,那就是控件的引用,属性节点以及局部变量,他们之间到底有哪些区别呢?        首先谈 ...

  2. Java基础之"=="和 和 equals 方法的区别

    一."=="操作符 ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作 ...

  3. 一年开发ASP.NET MVC4项目经验总结

    一年开发ASP.NET MVC4项目所用所学技术经验总结 阅读目录 文章背景 前端所用技术摘要 后端所用技术摘要 1. 文章背景 本人2014年从Java转行到C#从事BS项目的开发,刚开始接触的是A ...

  4. 《Pointers On C》读书笔记(第四章 语句)

    1.空语句只包含一个分号,它本身并不执行任何任务,其适用的场合是语法要求出现一条完整的语句,但并不需要它执行任何任务. 2.C语言中并不存在专门的“赋值语句”,赋值就是一种操作,在表达式内进行.通过在 ...

  5. 共享内存(shared memory)

    共享内存指在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存.由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache). 任何一个缓存的数据被更新后,由于其他处理 ...

  6. why-and-howto-calculate-your-events-per-second

    http://eromang.zataz.com/2011/04/12/why-and-howto-calculate-your-events-per-second/

  7. 微软提供的虚拟磁盘API

    https://msdn.microsoft.com/en-us/library/windows/desktop/dd323684(v=vs.85).aspx https://msdn.microso ...

  8. [转]关于HTTP服务器每个客户端2个连接的限制

    这两天猫在家里搞一个多线程的断点续传得C#程序,发现同时只能开2个线程下载,其他的线程一律要等待,这样就导致下载大文件时其他线程经常超时,郁闷好久.今天回公司无意中发现了一个帖子,终于真相大白了, 现 ...

  9. float 浮点数与零值0比较大小

    float x: 千万不要写x==0; 写出float x 与“零值”比较的if语句——一道面试题分析 写出float  x 与“零值”比较的if语句 请写出 float  x 与“零值”比较的 if ...

  10. 追踪神秘的成都Uber:月入2万元是现实还是传说

    4月6日,一个视频在网上疯转——在上海,明星佟大为驾驶着售价近100万元的特斯拉电动汽车,作为一名Uber的司机满市转悠着拉客. Uber——优步,如果你不知道这个词,那就OUT了.就是这样的一款软件 ...