题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3375
需要注意的是这个人每次去一个景点就回家,也就是这个人每次离家回家就只是vis一个点,这就让问题简化了好多
参考博客:http://blog.csdn.net/accelerator_/article/details/21299055
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)
#define bug printf("hihi\n")
#define eps 1e-8
typedef long long ll;
using namespace std;
#define N 50005
ll dp[N];
int head[N],Num;
struct stud{
int to,len,ne;
}e[N*2];
int num[N];
int n;
ll ans;
vector<int>go;
ll all;
inline void add(int u,int v,int len)
{
e[Num].to=v;
e[Num].len=len;
e[Num].ne=head[u];
head[u]=Num++;
}
void dfs1(int u,int pre,ll len)
{
dp[1]+=len*num[u];
for(int i=head[u];i!=-1;i=e[i].ne)
{
int to=e[i].to;
if(to==pre) continue;
dfs1(to,u,len+e[i].len*2);
num[u]+=num[to];
}
}
void dfs2(int u,int pre)
{
ans=min(ans,dp[u]);
for(int i=head[u];i!=-1;i=e[i].ne)
{
int to=e[i].to;
if(to==pre) continue;
dp[to]=dp[u]+(all-num[to]-num[to])*e[i].len*2;
dfs2(to,u);
}
}
int main()
{
int i,j,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(head,-1,sizeof(head));
Num=0;
i=n-1;
all=0;
int u,v,len;
while(i--)
{
scanf("%d%d%d",&u,&v,&len);
add(u,v,len);
add(v,u,len);
}
memset(num,0,sizeof(num));
int m;
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&u,&v);
num[u]=v;
all+=v;
}
dp[1]=0;
dfs1(1,-1,0);
ans=dp[1];
dfs2(1,-1);
printf("%lld\n",ans);
go.clear();
for(i=1;i<=n;i++)
if(dp[i]==ans) go.push_back(i);
for(i=0;i<go.size();i++)
{
if(i) printf(" ");
printf("%d",go[i]);
}
printf("\n");
}
return 0;
}