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;
}