P1395 会议

7 篇文章 1 订阅

题目

加强版,改一下a[i],和边权就好

通过先到一个点的距离,然后去遍历所有点

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
	ll ret=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
	while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
inline void write(ll zx){
	if(zx<0) putchar('-'),zx=-zx;
	if(zx<10) putchar(zx+'0');
	else{
		write(zx/10);
		putchar(zx%10+'0');
	}
}
int fir[200010],nxt[200010],w[200010],son[200010],tot,n;
ll a[100010],dis[100010],Min,ans;
void add(ll x,ll y,ll z){
	++tot;
	son[tot]=y;
	nxt[tot]=fir[x];
	fir[x]=tot;
	w[tot]=z;
}
void dfs(ll zx,ll fa){
    for(ll i=fir[zx];i;i=nxt[i]){
        if(son[i]!=fa){
            dfs(son[i],zx);
            a[zx]+=a[son[i]];//计算有几个游客 
            dis[zx]+=dis[son[i]]+a[son[i]]*w[i];//到这个节点的代价 
        }
    }
}
void fs(ll zx,ll fa){
    for(ll i=fir[zx];i;i=nxt[i]){
        if(son[i]!=fa){
            dis[son[i]]=dis[zx]-w[i]*a[son[i]]+w[i]*(a[1]-a[son[i]]);
			// 这个点到祖先+这条边要用几次。
			//自己的子树不用走这个点(a[son[i]]),所以其他(a[1]-a[son[i]])要走 
			//在dis[zx]里又多算了(w[i]*a[son[i]])次
			//dis[zx]-w[i]*a[son[i]] (先不算这条边)
			//dis[zx]-w[i]*a[son[i]]+w[i]*(a[1]-a[son[i]])  {加上其他点走这条边} 
			
            fs(son[i],zx);
        }
    }
}
int main(){
    n=read();
    for(ll i=1;i<=n;i++) a[i]=1;
    for(ll i=1;i<=n-1;i++){
    	ll x=read(),y=read();
        add(x,y,1);
		add(y,x,1);
    }
    dfs(1,0);
      
	fs(1,0);
    Min=2e18;
    for(ll i=1;i<=n;i++)if(Min>dis[i])Min=dis[i],ans=i;
        
    
    write(ans);
    cout<<' ';
    write(Min);putchar('\n');
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值