您的位置:首页 > 其它

FZU_Problem 2169 shadow

2014-08-08 15:04 323 查看
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支军队要向王都进军,并且消灭沿途经过的城市中的叛军。现给出N个城市的道路情况以及城市的叛军数量,问总共需要消灭多少叛军?



Input

第一行输入两个整数N,K,接下来输入N(1<=N<=100000)个整数Ai(0<=Ai<=10000),表示第i个城市的叛军数量。接下来输入K个大于等于1且小于等于N的整数,表示有军队的城市的编号。数据保证王都以及有军队的城市没有叛军。接下来输入N-1行,每行两个整数u、v,表示连接u和v的一条道路。每支军队只能沿着道路走,并且是其所在城市与王都之间的最短路线走。



Output

输出一行一个整数表示消灭的叛军数量。



Sample Input

4 20 3 0 03 41 22 32 4



Sample Output

3

//开始把有军队的城市都加入队列中,作为起始点,sum数组表示到这个城市累加消灭的叛军数,为了避免重复,遍历过后清0,d数组用来标记是否访问。直接用bfs解决。
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define maxn 100001
int a[maxn],b[maxn],d[maxn],sum[maxn];
int n,m;
vector<int>v[maxn];
void bfs()
{
queue<int>q;  //不能定义成全局变量
for(int i=0;i<maxn;i++)
d[i]=9999999;
memset(sum,0,sizeof(sum));
for(int i=1;i<=m;i++)
{
q.push(b[i]);
d[b[i]]=0;
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<v[u].size();i++)
{
int x=v[u][i];
if(d[x]>d[u]+1)
{
d[x]=d[u]+1;
sum[x]+=sum[u]+a[x];
sum[u]=0;
q.push(x);
}
}
}
}

int main()
{
int x,y,ans;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<=n;i++)
v[i].clear();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
ans=0;
bfs();
for(int i=1;i<=n;i++)
{
ans+=sum[i];
}
printf("%d\n",ans);
}
return 0;
}

//别人的方法,省时很多。
/*从有军队的城市BFS遍历,找到王都,沿途累加被杀掉的叛军数
用两个数组存储邻边关系
*/
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 100005
struct list
{
int val;  //当前点位置
int nxt;
}L[N*2]; //存储相临边的关系
struct point
{
int val;  //当前点位置
int k_num;  //累计杀死敌军数
}p,q;
int enemy
; //叛军
int army
;  //国军
int vis
;   //标记是否访问
int head
;
int n,k,id;
void add(int u,int v) //把u连在v后面
{
L[id].val=v;  //保存v的值,且拥有唯一id
L[id].nxt=head[u]; //// v的next为head[u],这里head[u]表示u的头结点的id,且把它连在v的后面
head[u]=id++;// 此时因为u的头结点已经连在v后面了,所以要更新头结点,把head[u]换成v的id
}
int bfs(int x)
{
int ret=0;
queue<point>s;
p.val=x;
p.k_num=enemy[x];
s.push(p);
vis[x]=1;
while(!s.empty())
{
p=s.front();
s.pop();
if(1==p.val)   //找到目标点
ret=p.k_num;
for(int i=head[p.val];i!=0;i=L[i].nxt)
{
int v=L[i].val;
if(0==vis[v])
{
vis[v]=1;
q.val=v;
q.k_num=p.k_num+enemy[v];
s.push(q);
}
}
}
return ret;
}

int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&enemy[i]);
for(int i=1;i<=k;i++)
scanf("%d",&army[i]);
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));
int ans=0;
id=1;
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i=1;i<=k;i++)
{
if(0==vis[army[i]])
ans+=bfs(army[i]);
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: