T1
类似于赛道修建
这道题一开始把
,
;
, ;
,;打错了从正解挂到
12
p
t
s
12pts
12pts呵呵我真的想拿头调代码
思路:因为是要最大化最小值,于是以
1
1
1为下界
n
−
1
n-1
n−1为上界二分
k
k
k值,然后
d
f
s
dfs
dfs判断是否合法。
考虑如何
d
f
s
dfs
dfs:递归
u
u
u的所有儿子
v
v
v,
v
v
v会为
u
u
u带来一条
l
e
n
v
+
1
len_v+1
lenv+1长度的边(
1
1
1是
u
u
u和
v
v
v之间的边)。开个
v
e
c
t
o
r
vector
vector记录当前节点下方所有的子链长度,然后对
v
e
c
t
o
r
vector
vector按照长度排序,此时我们有两种方案:
一:直接将
u
u
u子树上的链两两匹配(贪心思想),对
f
a
u
fa_u
fau不造成影响(如果链的长度为奇数就向当前
v
e
c
t
o
r
vector
vector里加入一条长度为
0
0
0的链进行匹配)
二:尝试将所有边两两匹配,尝试完成后选出一条无法匹配的边传给
u
u
u的父节点
f
a
u
fa_u
fau处理(注意这条边应该在保证其他边都匹配合法的情况下尽可能长显然)
当
u
=
=
1
u==1
u==1(根节点)时只有方案一可行,当
u
!
=
1
u\ !=1
u !=1时首先考虑方案二(因为要使传给父节点的边尽量长,能保证上面可行,这样更优),方案二不可行再考虑方案一,若两个方案都不可行则无解)。若选择方案二,直接将二分的长度作为要向上传的长度即可。
m
u
l
t
i
s
e
t
multiset
multiset比
v
e
c
t
o
r
vector
vector更优,但我不会告辞
#include <bits/stdc++.h>
#define vi vector<int>
#define pb push_back
using namespace std;
const int N=(int)2e5+50;
vi len[N];
int fir[N],tot,to[N],nxt[N],n,r,l,dp[N],mid;
inline void addedge(int x,int y){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;}
inline int read(){
int cnt=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
while(isdigit(c)){cnt=(cnt<<3)+(cnt<<1)+(c^48);c=getchar();}
return cnt*f;
}
inline bool check(int u,int mid,int val){
for(int i=0,j=len[u].size()-1;i<j;i++,j--){
if(i==mid)i++;
if(j==mid)j--;
if(len[u][i]+len[u][j]<val)return 0;
}
return 1;
}
inline int dfs(int u,int fa,int val){
len[u].clear();
for(int i=fir[u];i;i=nxt[i]){
int v=to[i];
if(v==fa)continue;
if(!dfs(v,u,val))return 0;
len[u].pb(dp[v]+1);
}
int sz=len[u].size();
if((fa&&!(sz&1))||(!fa&&(sz&1)))len[u].pb(0);
sort(len[u].begin(),len[u].end());
if(!fa){
for(int i=0;i<(sz>>1);i++)if(len[u][i]+len[u][sz-i-1]<val)return 0;
}
else{
if(!check(u,0,val))return 0;
int l=0,r=sz-1;
while(l<r){
int mid=(l+r+1)>>1;
if(check(u,mid,val))l=mid;
else r=mid-1;
}
dp[u]=len[u][l];
}
return 1;
}
int main(){
n=read();
for(int i=1;i<n;++i){int x=read(),y=read();addedge(x,y);addedge(y,x);}
l=1;r=n-1;
while(l<r){
mid=(l+r+1)>>1;memset(dp,0,sizeof(dp));
if(dfs(1,0,mid))l=mid;
else r=mid-1;
}
memset(dp,0,sizeof(dp));
if(dfs(1,0,l))printf("%d",l);
else printf("0");
return 0;
}
T2
咕咕咕
T3
咕咕咕
我感觉我即将从省选滚回联赛/kk