FZU2169:shadow(最短路)

来源:互联网 发布:电话变声软件 编辑:程序博客网 时间:2024/06/06 12:40

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 2 0 3 0 0 3 4 1 2 2 3 2 4

 Sample Output

3
 
简单的最短路SPFA,只是要加个优化,计算好友叛军的城市个数,每消灭一波叛军就减1,当没有叛军了就不用继续SPFA了
 
#include <stdio.h>#include <string.h>#include <algorithm>#include <queue>using namespace std;const int inf = 1<<30;const int L = 100005;struct Edges{    int x,y,w,next;} e[L<<2];int head[L];int dis[L];int vis[L];int cnt[L],hash[L],ss[L];int s[L];void AddEdge(int x,int y,int w,int k){    e[k].x = x,e[k].y = y,e[k].w = w,e[k].next = head[x],head[x] = k;}int relax(int u,int v,int c){    if(dis[v]>dis[u]+c)    {        dis[v] = dis[u]+c;        return 1;    }    return 0;}int SPFA(int src){    int i;    memset(vis,0,sizeof(vis));    dis[src] = 0;    queue<int> Q;    Q.push(src);    vis[src] = 1;    while(!Q.empty())    {        int u,v;        u = Q.front();        Q.pop();        vis[u] = 0;        for(i = head[u]; i!=-1; i=e[i].next)        {            v = e[i].y;            if(relax(u,v,e[i].w)==1 && !vis[v])            {                Q.push(v);                vis[v] = 1;            }        }    }}int main(){    int t,n,k;    int i,j;    while(~scanf("%d%d",&n,&k))    {        memset(e,-1,sizeof(e));        for(i = 1; i<=n; i++)        {            dis[i] = inf;            head[i] = -1;            hash[i] = 0;        }        int cnt = 0;        for(i = 1; i<=n; i++)        {            scanf("%d",&s[i]);            if(s[i])            {                hash[i] = 1;                cnt++;            }        }        for(i = 1; i<=k; i++)        {            scanf("%d",&ss[i]);        }        for(i = 0; i<2*(n-1); i+=2)        {            int x,y,w;            scanf("%d%d",&x,&y);            AddEdge(x,y,1,i);            AddEdge(y,x,1,i+1);        }        int ans = 0;        for(i = 1; i<=k; i++)        {            SPFA(ss[i]);            for(j = 1; j<=n; j++)            {                if(!hash[j])                    continue;                if(dis[s[j]]!=inf)                {                    hash[j] = 0;                    cnt--;                    ans+=s[j];                }            }            if(!cnt)                break;        }        printf("%d\n",ans);    }    return 0;}

0 0
原创粉丝点击