Live2D

# 【NOIP2018】赛道修建(正解)

NOIP题目怎么都好长



#include<bits/stdc++.h>
#define N 50005
using namespace std;

int n,m,u,v,w;

struct Edge
{
int next,to,dis;
}edge[N<<1];

inline void add_edge(int from,int to,int dis)
{
edge[cnt].to=to;
edge[cnt].dis=dis;
}

{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

bool vis[N];
int fa[N],len[N],Dis[N],ans[N];
int cal(int num,int limit)
{
int p=1,res=0;
for(register int i=num;i>p;--i)
{
if(vis[i]) continue;
while(p<i&&(len[p]+len[i]<limit||vis[p])) p++;
if(p<i&&!vis[p]&&len[p]+len[i]>=limit) res++;
p++;
}
return res;
}

void dfs(int u,int limit)
{
ans[u]=0;
{
int v=edge[i].to;
if(v==fa[u]) continue;
fa[v]=u;
Dis[v]=edge[i].dis;
dfs(v,limit);
ans[u]+=ans[v];
}
int num=0;
{
int v=edge[i].to;
if(v==fa[u]) continue;
len[++num]=Dis[v];
}
if(num)
{
sort(len+1,len+num+1);
len[0]=0;
int w=cal(num,limit);
ans[u]+=w;
int L=0,R=num,res;
while(L<=R)
{
int Mid=(L+R)>>1;
vis[Mid]=1;
if(cal(num,limit)==w) res=Mid,L=Mid+1;
else R=Mid-1;
vis[Mid]=0;
}
Dis[u]+=len[res];
}
if(Dis[u]>=limit) Dis[u]=0,ans[u]++;
}

bool check(int x)
{
//	cout<<"now is checking: "<<x<<endl;
memset(ans,0,sizeof(ans));
memset(Dis,0,sizeof(Dis));
int num=0;
dfs(1,x);
if(ans[1]>=m) return true;
return false;
}

int main()
{
int l=1,r=0;
for(register int i=1;i<=n-1;++i)
{
r+=w;
}
int ans;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}

$$\text{这里是tqr，联系我请加QQ735748368}$$
posted @ 2019-11-04 21:32  tqr06  阅读(104)  评论(0编辑  收藏  举报