【NOIP2018提高组D1T3】赛道修建

唉,这题考场想到了,就是细节搞爆了。。。
主要是二分答案然后判一下,每次深搜(类似贪心)即可。

#include
#include
#include
using namespace std;
struct node{int v,fr,l;}e[100010];
int tail[50010],len[50010],a[50010],n,m,l=0,r=0,mid,ans=0,cnt=0,tot;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=x*10+c-48,c=getchar();
	return x;
}

void add(int u,int v,int l) {e[++cnt]=(node){v,tail[u],l}; tail[u]=cnt;}

int pd(int x,int l,int r)
{
	int s=0;
	while (l<r)
	{
		if (r==x) r--;
		while (l<r && a[l]+a[r]<mid) l++;
		if (l==x) l++;
		if (l<r) s++,l++,r--;
	}
	return s;
}

void dg(int x,int fa)
{
	for (int p=tail[x];p;p=e[p].fr)
		if (e[p].v!=fa) dg(e[p].v,x);
	int m=0;
	for (int p=tail[x];p;p=e[p].fr)
		if (e[p].v!=fa)
		{
			len[e[p].v]+=e[p].l;
			if (len[e[p].v]>=mid) tot++;
			else a[++m]=len[e[p].v];
		}
	if (m==0) return;
	else if (m==1) {len[x]+=a[1]; return;}
	sort(a+1,a+m+1);a[0]=0;
	int le=0,ri=m,mi,s=0,ma=pd(0,1,m);
	while (le<=ri)
	{
		mi=le+ri>>1;
		if (pd(mi,1,m)==ma) s=mi,le=mi+1;
		else ri=mi-1;
	}
	tot+=ma;len[x]+=a[s];
}

int main()
{
	freopen("track.in","r",stdin);
	freopen("track.out","w",stdout);
	n=read(),m=read();
	for (int i=1,a,b,ll;i<n;i++)
	{
		a=read(),b=read(),ll=read();
		add(a,b,ll),add(b,a,ll);r+=ll;
	}
	while (l<=r)
	{
		mid=l+r>>1;
		memset(len,0,sizeof(len));
		tot=0;dg(1,0);
		if (tot>=m) ans=mid,l=mid+1;
		else r=mid-1;
	}
	printf("%d\n",ans);
	return 0;
}

你可能感兴趣的:(NOIP,dfs,二分)