一个各种例题的博客点击打开链接
s
Holiday's Accommodation
HDU - 4118#include<iostream>
#include<iomanip>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<vector>
#include<stack>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
typedef long double lb;
typedef pair<int,int> pii;
const int inf= 0x3f3f3f3f;
const double eps= 1e-8;
const int maxn = 200000+10;
//之所以用ll是为了不爆int;
ll dp[maxn];//是用来存这个点 某一边有多少个点;
ll res;//结果
bool mark[maxn];//用来标记,访问过就不要再访问了,防止倒回去;
vector<pair<int,int> >v[maxn];
int n;
ll MIN(ll a,ll b)
{
return a<b?a:b;
}
void dfs(int id,int w,int num)
{
dp[id]=0;
mark[id]=true;
int sz=v[id].size();
for(int i=0;i<sz;i++)
{
int b=v[id][i].first;
int c=v[id][i].second;
if(mark[b]) continue;
dfs(b,c,num);
dp[id]+=dp[b];
}
dp[id]++;
res+=MIN(dp[id],n-dp[id])*w*2;//这一步就是核心了,就是一定能找到
//一种构造使得这条边左边的点到右边去,右边的点到左边去,当然如果做有点数不想等,就按少的算,总不可能挤一个坑;
//因为是又进去的又出去的,所以这条边被用了两遍;
//这个结果一定是最优的,至于为什么,因为无法在多用这条边2次了;
}
int main()
{
int T;
scanf("%d",&T);
int cnt=0;
while(T--)
{
cnt++;
scanf("%d",&n);
for(int i=1;i<=n;i++)
v[i].clear();
memset(mark,false,sizeof(mark));
res=0;
for(int i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
v[a].push_back(make_pair(b,c));
v[b].push_back(make_pair(a,c));
}
dfs(1,0,n);
cout<<"Case #"<<cnt<<": "<<res<<endl;
}
return 0;
}