链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737
思路: 对于每一条边,我们如果想要使得他发挥最大价值,其实就是这条边被用了 min(sonsz[ u ], sonsz[ v ])次,那么我如果找到一个点使得删掉这个点之后所有的联通分支的点的个数都小于等于n/2个点,那么就可以构造出一种方案使得每条边被使用min(sonsz[ u ], sonsz[ v ])次。所以就是找树的重心就可以了。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int ,ll > pil;
const int N =1e5+5;
const int inf =0x3f3f3f3f;
int sz[N];
vector< pil >ve[N];
int n;
ll ans;
int zx;
int mn;
void dfs1(int u,int fa)
{
sz[u]=0;
int tmp=0;
for(int i=0;i<ve[u].size();i++){
int v=ve[u][i].first;
if(v==fa) continue;
dfs1(v,u);
tmp=max(tmp,sz[v]+1);
sz[u]+=(sz[v]+1);
}
tmp=max(tmp,n-sz[u]-1);
if(tmp<mn)
{
mn=tmp;
zx=u;
}
}
void dfs2(int u,int fa,ll dis)
{
ans+=dis;
for(int i=0;i<ve[u].size();i++){
int v=ve[u][i].first;
ll w=ve[u][i].second;
if(v==fa) continue;
dfs2(v,u,dis+w);
}
}
int main()
{
int u,v; ll w;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d %d %lld",&u,&v,&w);
ve[u].push_back(pil(v,w));
ve[v].push_back(pil(u,w));
}
mn=inf;
dfs1(1,1);
ans=0;
//printf("zx %d\n",zx);
dfs2(zx,zx,0);
printf("%lld\n",ans);
return 0;
}
那么直接对于每条边进行价值乘也对。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int ,ll > pil;
const int N =1e5+5;
int sz[N];
vector< pil >ve[N];
int n;
ll ans;
void dfs(int u,int fa)
{
sz[u]=1;
for(int i=0;i<ve[u].size();i++){
int v=ve[u][i].first;
if(v==fa) continue;
dfs(v,u);
ll w=ve[u][i].second;
ans+=w*min(sz[v],n-sz[v]);
sz[u]+=sz[v];
}
}
int main()
{
int u,v; ll w;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d %d %lld",&u,&v,&w);
ve[u].push_back(pil(v,w));
ve[v].push_back(pil(u,w));
}
dfs(1,1);
printf("%lld\n",ans);
return 0;
}
其实和hdu 4118 一毛一样
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4118
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,ll > pil;
const int N =1e5+5;
const int inf =0x3f3f3f3f;
int sz[N];
vector< pil >ve[N];
int n;
ll ans;
int zx;
int mn;
void dfs1(int u,int fa)
{
sz[u]=0;
int tmp=0;
for(int i=0; i<ve[u].size(); i++)
{
int v=ve[u][i].first;
if(v==fa)
continue;
dfs1(v,u);
tmp=max(tmp,sz[v]+1);
sz[u]+=(sz[v]+1);
}
tmp=max(tmp,n-sz[u]-1);
if(tmp<mn)
{
mn=tmp;
zx=u;
}
}
void dfs2(int u,int fa,ll dis)
{
ans+=dis;
for(int i=0; i<ve[u].size(); i++)
{
int v=ve[u][i].first;
ll w=ve[u][i].second;
if(v==fa)
continue;
dfs2(v,u,dis+w);
}
}
void init()
{
for(int i=0;i<=n+2;i++) ve[i].clear();
for(int i=0;i<=n+2;i++) sz[i]=0;
}
int main()
{
int T;
scanf("%d",&T);
int kk=0;
while(T--)
{
int u,v;
ll w;
scanf("%d",&n);
init();
for(int i=1; i<n; i++)
{
scanf("%d %d %lld",&u,&v,&w);
ve[u].push_back(pil(v,w));
ve[v].push_back(pil(u,w));
}
mn=inf;
dfs1(1,1);
ans=0;
//printf("zx %d\n",zx);
dfs2(zx,zx,0);
printf("Case #%d: %lld\n",++kk,ans*2);
}
return 0;
}