樹形動態規划 fjutoj


第四集,聚集城市

TimeLimit:1000MS  MemoryLimit:128MB 64-bit integer IO format:%lld   Problem Description

在小A解讀完手機信息后,得到了特工們的位置情報以及他們最近將會又一次聚會(除了談論了關於抓捕小A和小C的事情外,主要談論了關於走私事情…)

因為小C原本是他們的內部人員,所以她知道這個組織有一個習慣,即特工們每次選擇聚會的城市,他們都會選擇使所有組員所在市距離聚會城市的路程的和最小的城市,而且每個城市最多有一名特工

現在,小A知道了特工們的所在位置,小A根據城市地圖繪制了一副簡易圖,圖的如下信息:

1,有一副n個節點的雙向無環圖,每個節點表示一個城市。

2,每條邊默認距離為1

3,有m個城市里住了他們的組員。

根據這些信息,得出一個城市編號X1<=X<=n),使X到這m個城市的距離的和最小。

小A知道這是他反擊的機會,他需要證據,他不想在和小C一直過着顛簸流離的逃亡生活。他需要獲取更多關於走私的信息,他才有足夠多的證據端了這個組織.因此,他必須找到這個聚會城市、

 

Input

有多組測試案例

第一行輸入兩個正整數n和m。(2<n<=10000,1<m<=n)

第二行接下來輸入m個正整數mi,表示城市mi有1名特工(mi!=mj,i!=j)、

接下來有n-1行,每一行輸入兩個正整數a和b,表示城市a和城市b相連、 

 

Output

對於每組測試案例,輸出符合的城市編號,如果有多個城市符合要求,則輸出編號最小的那個城市、

SampleInput
8 4
4 3 6 7
4 7
5 6
1 8
1 3
7 5
5 2
5 3

SampleOutput
5

 

 1 #include<cstdio>
2 #include<cstring>
3 #include<vector>
4 using namespace std;
5 const int maxn = 10000+5;
6 vector<int>e[maxn];
7 int has[maxn],vis[maxn],minLen[maxn],cot[maxn],dp[maxn],n,m,num;
8 //has:記錄哪幾個城市需要到達
9 //vis:記錄是否有搜索過
10 //minLen:記錄1到所有需要到達城市的最小距離
11 //cot:記錄兒子有多少個需要到達的城市
12
13 //初始化
14 void init()
15 {
16 memset(vis,0,sizeof(vis));
17 memset(has,0,sizeof(has));
18 memset(cot,0,sizeof(cot));
19 memset(minLen,0,sizeof(minLen));
20 memset(dp,0,sizeof(dp));
21 for(int i= 1 ; i<=n; i++)
22 e[i].clear();
23 }
24
25 //計算最短長度和每個點兒子有多少個需要到達的城市
26 int dfs1(int now,int dep)
27 {
28 int temp=0;
29 if(has[now])
30 temp=1;
31 minLen[now]=dep;
32 int len=e[now].size();
33 for(int i=0; i<len; i++)
34 {
35 int to =e[now][i];
36 if(!vis[to])
37 {
38 vis[to]=1;
39 temp=temp+dfs1(to,dep+1);
40 }
41 }
42 cot[now]=temp;
43 return temp;
44 }
45
46 void dfs2(int now)
47 {
48 int len=e[now].size();
49 for(int i=0; i<len; i++)
50 {
51 int to = e[now][i];
52 if(!vis[to])
53 {
54 vis[to]=1;
55 dp[to]=dp[now]+m-2*cot[to];//狀態轉移方程
56 //dp[to] = dp[now] + m-cot[to](離父節點的所有城市+1) -cot[to](離子節點的所有城市-1);
57 dfs2(to);
58 }
59 }
60 }
61
62 int main()
63 {
64 while(~scanf("%d%d",&n,&m))
65 {
66 init();
67 for(int i = 0; i<m; i++)
68 {
69 scanf("%d",&num);
70 has[num]=1;
71 }
72 for(int i = 0 ; i <n-1; i++)
73 {
74 int x,y;
75 scanf("%d%d",&x,&y);
76 e[x].push_back(y);
77 e[y].push_back(x);
78 }
79 vis[1]=1;
80 dfs1(1,0);
81 for(int i=1; i<=n; i++)
82 {
83 if(has[i])
84 dp[1]+=minLen[i];
85 }
86 memset(vis,0,sizeof(vis));
87 vis[1]=1;
88 dfs2(1);
89 int Min_dp=dp[1],lie=1;
90 for(int i=1; i<=n; i++)
91 if(dp[i]<Min_dp)
92 {
93 Min_dp=dp[i];
94 lie=i;
95 }
96 printf("%d\n",lie);
97 }
98 return 0;
99 }

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com