20201024B组T3 兔子
看错题了没发现有环是我没想到的
题目大意
一个类似菊花图的东东,叶子节点上有连边,放置k个物品,求每个点到这k个物品最短距离的最大值
TJ
“最大的最小值”显然二分,然后枚举覆盖根的点,将删去覆盖点后出现链直接求每一条的贡献
#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
const int INF=1e9+7;
using namespace std;
const int N=1e3;
const int M=3000;
struct edge{
int st,en,next;
}E[M+10];
int n,m,k,l,r,mid,ans,st,en,tot;
int last[N+10],dis[N+10],x,y,S,d[N+10],data[N+10];
bool bz[N+10];
void add(int x,int y){
E[++tot]=(edge){x,y,last[x]};
last[x]=tot;
}
void dfs(int x){
for(int p=last[x];p;p=E[p].next){
int y=E[p].en;
if(dis[y])continue;
if(y==S){
dis[x]=1;
continue;
}
dis[y]=dis[x]+1;
dfs(y);
dis[x]=min(dis[x],dis[y]+1);
}
}
void dfs2(int x,int depth){
if(!depth)return;
for(int p=last[x];p;p=E[p].next){
int y=E[p].en;
if(bz[y])continue;
bz[y]=1;
dfs2(y,depth-1);
}
}
int work(int x){
int s=1;
st=0;en=1;
data[1]=x;
bz[x]=1;
while(st<en){
x=data[++st];
for(int p=last[x];p;p=E[p].next){
int y=E[p].en;
if(bz[y])continue;
bz[y]=1;
s++;
data[++en]=y;
}
}
return s;
}
bool check(int x,int len){
bz[x]=1;
dfs2(x,len);
int s=1;
fo(i,1,n){
if(!bz[i]){
int y=work(i);
s+=(y+2*len)/(2*len+1);
}
}
return s<=k;
}
bool pd(int x){
fo(i,1,n){
if(i==S)continue;
if(dis[i]<=x){
memset(bz,0,sizeof(bz));
if(check(i,x))return 1;
}
}
memset(bz,0,sizeof(bz));
bz[S]=1;
fo(i,1,n)bz[i]=(dis[i]<=x);
int s=1;
fo(i,1,n){
if(!bz[i]){
int y=work(i);
s+=(y+2*x)/(2*x+1);
}
}
return s<=k;
}
int main(){
freopen("rabbit.in","r",stdin);
freopen("rabbit.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
fo(i,1,m){
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
d[x]++;d[y]++;
}
fo(i,1,n){
if(d[i]>2){
S=i;
break;
}
}
if(!S){
ans=(n+1)/(k+1)-1;
printf("%d\n",ans);
return 0;
}
r=n;
for(int p=last[S];p;p=E[p].next){
int y=E[p].en;
if(dis[y])continue;
dis[y]=1;
dfs(y);
}
while(l<r-1){
mid=(l+r)/2;
if(pd(mid))r=mid;
else l=mid;
}
printf("%d\n",r);
return 0;
}