poj 1935(树形dp)
题目链接:http://poj.org/problem?id=1935
思路:首先我们考虑从源点出发到所有自己想要经过的点然后在回到源点sum,显然每条边都必须经过源点(这个我们可以一次dfs求出),但题目的意思是可以不用回到源点,那么我们可以再求源点到所有要经过的点的最远距离ans,于是答案便是sum-ans.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN 55555 7 #define FILL(a,b) memset(a,b,sizeof(a)) 8 9 struct Edge{ 10 int v,w,next; 11 }edge[MAXN<<1]; 12 13 int n,m,k,NE; 14 int head[MAXN]; 15 16 void Insert(int u,int v,int w) 17 { 18 edge[NE].v=v; 19 edge[NE].w=w; 20 edge[NE].next=head[u]; 21 head[u]=NE++; 22 } 23 24 int dist[MAXN],sum; 25 bool vis[MAXN]; 26 27 void dfs(int u,int father) 28 { 29 for(int i=head[u];i!=-1;i=edge[i].next){ 30 int v=edge[i].v,w=edge[i].w; 31 if(v==father)continue; 32 dist[v]=dist[u]+w; 33 dfs(v,u); 34 if(vis[v])sum+=2*w,vis[u]=true; 35 } 36 } 37 38 39 int main() 40 { 41 int u,v,w,ans; 42 while(~scanf("%d%d",&n,&k)){ 43 NE=0; 44 FILL(head,-1); 45 for(int i=1;i<n;i++){ 46 scanf("%d%d%d",&u,&v,&w); 47 Insert(u,v,w); 48 Insert(v,u,w); 49 } 50 scanf("%d",&m); 51 FILL(vis,false); 52 while(m--){ 53 scanf("%d",&u); 54 vis[u]=true; 55 } 56 dist[k]=0; 57 sum=0; 58 dfs(k,-1); 59 ans=0; 60 for(int i=1;i<=n;i++)if(vis[i]){ 61 ans=max(ans,dist[i]); 62 } 63 printf("%d\n",sum-ans); 64 } 65 return 0; 66 }