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;
}

最新文章

  1. 我的iOS开发系列博文
  2. iOS 关于修饰代理用weak还是assign
  3. 有关使用seajs和template模板的总结
  4. sprint演示Scrum 项目7.0
  5. jQuery中过滤选择器first和first-child的区别
  6. Base64.java 工具类
  7. Mysql的函数使用方法
  8. 计算机体系结构 -内存优化vm+oom
  9. 下拉框上移、下移、添加、移除demo
  10. 多线程面试题(Google)
  11. redis五种数据类型的使用
  12. 饥饿的牛(hunger)
  13. 【CNMP系列】CNMP之路,系统起步。
  14. java8新特性,使用流遍历集合
  15. java 整型数组基本排序,冒泡,快速选择,插入,归并
  16. 【问题解决】java中为什么不建议使用DataInputStream 的readLine()方法
  17. Java-NIO(五):通道(Channel)的数据传输与内存映射文件
  18. how tomcat works 读书笔记 十一 StandWrapper 下
  19. 解决springboot jar包冲突
  20. 爱奇艺直播 - 春晚直播业务API架构

热门文章

  1. Linux命令之修改主机名
  2. HDU4323-Magic Number(levenshtein distance-编辑距离)
  3. 5G关键技术研究方向
  4. js中this的四种使用方法
  5. [LeetCode]题解(python):141-Linked List Cycle
  6. 四轴飞行器1.5 各种PID对比分析及选择
  7. SQL Server 储存过程的output 参数
  8. 老男孩python第六期
  9. Git安装及基本使用
  10. web前端的发展态势