雅礼培训 Problem B 【图论 + 贪心】

题意

A和B在树上轮流选点,记A的联通块个数为\(x\),B的联通块个数为\(y\)
A使\(x - y\)最大,B使\(x - y\)
二人采取最优策略,求\(x-y\)

题解

树联通块个数 = 点数 - 边数

有这个转化,我们记二人选的点数为P,联通块内边数为E
\(ans = (P_{A} - E_{A}) - (P_{B} - E_{B})\)
其中\(P\)的差是固定的
我们要求的是\(E_{A} - E_{B}\)

A会使这个值尽量大,会使其选的边尽量少
B会使这个值尽量小,会使其选的边尽量少

所以二者都会尽量少地选边

但二人是直接选点的,考虑将边转为到点上

当一条边两端颜色相同,则计入对应的贡献,否则不计入贡献
如果说边权为1的话,我们将一条边的权值分配到两端的点上
A选就是-1,B选就是1
这样的话,如果两端的点颜色不同,贡献为0;颜色相同,贡献为对应的值*2

而这样,每个点的权值就是每个点的度数
所以我们只需要将度数排序,贪心选择即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k; k = ed[k].nxt)
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
    return out * flag;
}
int de[maxn],n,A,B;
int main(){
    n = read();
    for (int i = 1; i < n; i++){
        de[read()]++;
        de[read()]++;
    }
    sort(de + 1,de + 1 + n);
    for (int i = 1; i <= n; i++){
        if (i & 1) A -= de[i];
        else B += de[i];
    }
    printf("%d\n",(n & 1) + ((B + A) >> 1));
    return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/8696503.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值