FZU2169:shadow(最短路)
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; }