图论思维习题

CF1339D. Edge Weight Assignment (构造)

链接:https://codeforces.com/contest/1339/problem/D

题意:给定一颗 n 个节点的树,让你为 n -1 条边分配权值,使得任意两个叶节点之间的边权异或值为 0 。问最少和最多能分配多少个不同的权值。

思路

  • 最少:可以发现路径长度为偶数的话,可以设为同一个数。奇数的话,就至少需要 3 个数。因此若叶节点两两之间的距离为偶数,那么答案就是 1,否则为 3 。
  • 最多:可以发现如果两个叶节点距离为 2,那么这两个点的权值必须设置为相同的。因此边权可以从 n -1 开始减少。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
int n;
vector<int> e[maxn];
int in[maxn],depth[maxn],f[maxn];
void dfs(int u,int fa=-1)
{
    for(auto v: e[u])
    {
        if(v==fa) continue;
        depth[v]=depth[u]+1;
        dfs(v,u);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n-1; ++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        e[u].push_back(v);
        e[v].push_back(u);
        in[u]++,in[v]++;
    }
    for(int i=1; i<=n; ++i)
        if(in[i]==1) f[e[i][0]]++;
    int ans=n-1;
    for(int i=1; i<=n; ++i)
        ans-=max(0,f[i]-1);
    dfs(1);
    bool f1=0,f2=0;
    for(int i=1; i<=n; ++i)
        if(in[i]==1)
            if(depth[i]&1) f1=1;
            else f2=1;
    printf("%d %d\n",f1&&f2?3:1,ans);
    return 0;
}

CF1337C Linova and Kingdom( 贪心)

链接:https://codeforces.com/contest/1337/problem/C

题意:给定一个n个节点的无向连通图,城市1为首都,选择k个城市作为工业城市,其余城市为旅游城市。现有k个使者从工业城市出发去首都。每个使者每经过一个旅游城市,愉悦值都会+1,问最大的愉悦值是多少?

思路:将工业城市建得里首都越远越好。考虑将一个城市建为工业城市,那么它的子节点必然也已经是工业城市了。因为如果它的子节点还不是工业城市的话,选它的子节点会更优。所以将这个城市建设为工业城市的快乐值是:该城市的深度 - 子节点的个数。选择前 k 个最大的值即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+10;
int n,k;
vector<int> e[maxn];
int depth[maxn],sz[maxn];
void dfs(int u,int fa)
{
    sz[u]=1;
    for(auto v: e[u])
    {
        if(v==fa) continue;
        depth[v]=depth[u]+1;
        dfs(v,u);
        sz[u]+=sz[v];
    }
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n-1; ++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        e[u].push_back(v);
        e[v].push_back(u);
    }
    depth[1]=1;
    dfs(1,0);
    for(int i=1; i<=n; ++i) depth[i]-=sz[i];
    sort(depth+1,depth+1+n);
    ll ans=0;
    for(int i=n; i>=n-k+1; --i) ans+=depth[i];
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值