slim cut 2016ACM/ICPC Hong Kong live match H

https://vjudge.net/contest/392376#problem/H

Learn from

https://blog.csdn.net/u014609452/article/details/68482711?locationNum=10&fps=1

For the time divide and conquer, it is not necessary to do it on the line segment tree, and directly open the vector and array dynamically to ensure that there is only Logn*m space.

Sort the edges from largest to smallest, and then enumerate a boundary. The current largest cut edge is edg[l+1].w, and then the edges from 1-l are not cut, but smaller than the boundary [l+ The edges of 2,m] are randomly connected, that is, now there is a bunch of connected blocks connected by the big edges randomly combined into two parts. To make the answer the smallest, we need the smaller part to be the largest. So you can use bitset to make 01 backpack DP, and judge the largest part of the smaller half.

Use union check to maintain the size of connected blocks, and determine from which time the size of each connected block exists, and then divide and conquer the time, so that the 01 backpack dp can only increase from top to bottom in divide and conquer. , We can get 01 knapsack dp at every time when l==r, then the complexity is O(mlogn * n/W)

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

const int maxn=14010;
const int maxm=30010;

int n,m;
int sz[maxn],f[maxn],clk[maxn];
struct ed
{
	int u,v,w;
	bool operator <(const ed &b)const
	{
		return w>b.w;
	}
}edg[maxm];
struct event
{
	int l,r,w;
	event(int a=0,int b=0,int c=0)
	{
		l=a;r=b;w=c;
	}
};
vector<event> vec;
double ans=1e30;
bitset<maxn> B;

inline int find(int x)
{
	if(f[x]!=x)
		f[x]=find(f[x]);
	return f[x];
}

inline void prework()
{
	scanf("%d%d",&n,&m);
	int u,v,w;
	for(int i=1;i<=m;i++)
	{	
		scanf("%d%d%d",&u,&v,&w);
		++u;++v;
		edg[i]=ed{u,v,w};
	}
	sort(edg+1,edg+1+m);
	for(int i=1;i<=n;i++)
		f[i]=i,sz[i]=1,clk[i]=0;
	int x,y;
	for(int i=1;i<=m;i++)
	{
		x=find(edg[i].u),y=find(edg[i].v);
		if(x==y) continue;
		vec.push_back(event(clk[x],i-1,sz[x]));
		vec.push_back(event(clk[y],i-1,sz[y]));
		f[x]=y;sz[y]+=sz[x];clk[y]=i;
	}
	for(int i=1;i<=n;i++)
	if(f[i]==i)
		vec.push_back(event(clk[i],m,sz[i])); 
}

inline void solv(int l,int r,vector<event> &vec) 
{
	bitset<maxn> tmp;tmp=B;int len=vec.size();
	if(l==r)
	{
		for(int i=0;i<len;i++)
		if(vec[i].l<=l && r<=vec[i].r)
			B|=B<<vec[i].w;
		for(int i=1;i<=n/2;i++)
		if(B[i])
			ans=min(ans,(double)edg[l+1].w/i);;
		B=tmp;
		return;
	}
	vector<event> v1,v2;
	int mid=(l+r)>>1;
	for(int i=0;i<len;i++)
	if(vec[i].l<=l && r<=vec[i].r)
		B|=B<<vec[i].w;
	else
	{
		if(vec[i].l<=mid) v1.push_back(vec[i]);
		if(vec[i].r>mid) v2.push_back(vec[i]);
	}
	solv(l,mid,v1);
	solv(mid+1,r,v2);
	B=tmp;
}

inline void mainwork()
{
	B[0]=1;
	solv(0,m,vec);
}

inline void print()
{
	printf("%.11f\n",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

Guess you like

Origin blog.csdn.net/liufengwei1/article/details/108402108