http://acm.fzu.edu.cn/problem.php?pid=2169
Problem
|
题意:N<=10万个点,N-1条边使所有点连通,点编号为1~N,1号点为国王所在地,给出K个编号表示这K个点有国王的军队,给出Ai表示第i个点有Ai个叛军,国王所在地和有国王军的地方没叛军。现在国王的军队以最短路向国王所在地移动,消灭沿途所有叛军,求消灭的叛军数。
解:用STL的set记国王军所在地,从国王所在地开始宽搜,从当前点u扩展节点时记录扩展节点v来自哪里,from[v]=u。搜到一个国王军就把之前走的这条路上的点的叛军数加到ans里,并且对沿途的点标记geted[x]=true,一开始先标记国王所在地geted[0]=true,这样每次找到一个国王军就把国王军到geted为true的点之间的叛军数加到ans里,并且统计找到的国王军数cnt++。cnt==K时就找够全部国王军了,结束。是不是很碉,只要一次宽搜就得了耶!
1 #include<iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include<vector>
6 #include<queue>
7 #include<set>
8 #define MAXN 101111
9 #define RE freopen("in.txt","r",stdin);
10
11 using namespace std;
12
13 struct Edge
14 {
15 int u,v;
16 int next;
17 };
18 Edge e[MAXN*2];
19 int first[MAXN];
20 int en;
21
22 void add(int u,int v)
23 {
24 e[en].u=u;
25 e[en].v=v;
26 e[en].next=first[u];
27 first[u]=en;
28 en++;
29 }
30
31 int n,k,cnt;
32 int a[MAXN];
33 set<int> b;
34 bool walked[MAXN];
35 bool geted[MAXN];
36 queue<int> v;
37 int from[MAXN];
38 int farm();
39 void init();
40
41 int main()
42 {
43 //RE
44 while(scanf("%d%d",&n,&k)!=EOF)
45 {
46 farm();
47 }
48 return 0;
49 }
50
51 int farm()
52 {
53 int i,j,x,y;
54 init();
55 for(i=0; i<n; i++)
56 scanf("%d",&a[i]);
57 for(i=0; i<k; i++)
58 {
59 scanf("%d",&x);
60 x--;
61 b.insert(x);
62 }
63 for(i=0; i<n-1; i++)
64 {
65 scanf("%d%d",&x,&y);
66 x--;y--;
67 add(y,x);
68 add(x,y);
69 }
70 long long ans=0;
71 while(!v.empty()) v.pop();
72 v.push(0);
73 walked[0]==true;
74 geted[0]=true;
75 while(!v.empty())
76 {
77 int now=v.front();
78 v.pop();
79 //cout<<now<<‘!‘;
80 if(b.find(now)!=b.end())
81 {
82 //cout<<now<<‘,‘;
83 x=now;
84 while(!geted[x])
85 {
86 geted[x]=true;
87 ans+=a[x];
88 x=from[x];
89 }
90 cnt++;
91 if(cnt==k) break;
92 continue;
93 }
94 for(j=first[now]; j!=-1; j=e[j].next)
95 {
96 //cout<<j<<‘?‘;
97 int next=e[j].v;
98 if(!walked[next])
99 {
100 walked[next]=true;
101 v.push(next);
102 from[next]=now;
103 }
104 }
105 }
106 printf("%lld\n",ans);
107 return 0;
108 }
109
110
111 void init()
112 {
113 memset(e,0,sizeof(e));
114 memset(first,-1,sizeof(first));
115 memset(walked,false,sizeof(walked));
116 memset(geted,false,sizeof(geted));
117 b.clear();
118 cnt=0;
119 en=0;
120 }
话说我交的时候突然想起set没清空,不过还是过了,难道只有一组数据…
不过耗时好像比其他方法久……好像可以手动开栈 深搜,我也不太懂怎么弄的