集训队作业2018: 树(点分治+K短路)

题解:
最近学数分学到意识模糊,做到OI题冷静一下。

联通块强制选根,然后用dfs序转化为一个路径然后就是做K短路了。

用点分治即可在图大小为 O ( n log n ) O(n \log n) 的图上做K短路,时间复杂度 O ( n log 2 n + k log k ) O(n \log ^2 n + k\log k)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair <int,int> pii;
typedef pair <LL,int> pLi;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=1e5+50;
int n,k,a[N],G;
vector <int> edge[N];
int vis[N],dep[N],fa[N],sze[N],mx,total;

inline void calcG(int x,int f) {
	int mx_son=0;
	sze[x]=1;
	for(auto v:edge[x])
		if(!vis[v] && (v^f)) {
			calcG(v,x); 
			sze[x]+=sze[v];
			mx_son=max(mx_son,sze[v]);
		}
	mx_son=max(mx_son,total-sze[x]);
	if(mx>mx_son) G=x, mx=mx_son;
}
inline void dfs(int x,int f) {
	sze[x]=1;
	for(auto v:edge[x])
		if(!vis[v] && (v^f)) dfs(v,x), sze[x]+=sze[v];
}
inline void solve(int x,int f) {
	dep[x]=dep[f]+1; 
	fa[x]=f; vis[x]=1;
	for(auto v:edge[x]) 
		if(!vis[v]) {
			dfs(v,x);
			total=mx=sze[v];
			calcG(v,x);
			solve(G,x);
		}
}

namespace KSP {
	const int src=1, des=2, N=3345678, M=23456789;
	int g[N],nt[N],vt[N],ec,tot=2;
	LL w[N],dis[N]; int vis[N],isfa[N];
	inline void add(int x,int y,LL ww) {nt[++ec]=g[x]; g[x]=ec; vt[ec]=y; w[ec]=ww;}
	struct node {
		node *lc,*rc;
		int dis; pLi val;
	} *rt[N],Pool[M],*pool=Pool; 
	inline node* newnode(pLi v=pLi(0,0)) {
		node *t=++pool;
		t->lc=t->rc=NULL;
		t->dis=0; t->val=v;
		return t;
	}
	struct data {
		node* now;
		LL base;
		data(node *now,LL base) : now(now),base(base) {}
		friend inline bool operator <(const data &a,const data &b) {
			return a.base+a.now->val.first>b.base+b.now->val.first;
		}
	};
	inline node* merge(node *x,node *y) {
		if(!x) return y;
		if(!y) return x;
		if(x->val>y->val) swap(x,y);
		node *z=newnode(); *z=*x;
		z->rc=merge(z->rc,y);
		if(!z->lc || (z->rc && z->rc->dis>z->lc->dis)) swap(z->lc,z->rc);
		z->dis=(z->rc ? z->rc->dis : -1)+1;
		return z;
	}
	inline void getdis() {
		for(int i=2;i<=tot;i++) dis[i]=1e18;
		for(int e=g[1];e;e=nt[e])
			dis[vt[e]]=min(dis[vt[e]],(LL)w[e]);
		for(int i=3;i<=tot;i++)
			for(int e=g[i];e;e=nt[e])
				dis[vt[e]]=min(dis[vt[e]],dis[i]+w[e]);
		for(int i=1;i<=tot;i++)
			for(int e=g[i];e;e=nt[e])
				if(!isfa[vt[e]] && dis[vt[e]]==dis[i]+w[e]) isfa[vt[e]]=i;
				else rt[vt[e]]=merge(rt[vt[e]],newnode(pLi(w[e]-(dis[vt[e]]-dis[i]),i)));
	}
	int exi[N];
	inline void dfs2(int x) {
		if(!isfa[x] || exi[x]) return;
		exi[x]=1; 
		dfs2(isfa[x]);
		rt[x]=merge(rt[x],rt[isfa[x]]);
	}
	inline void solve() {
		getdis();
		if(k==1) {cout<<dis[2]<<'\n'; return;}
		k--;
		for(int i=1;i<=tot;i++) dfs2(i);
		
		priority_queue <data> q;
		q.push(data(rt[2],0));
		
		while(k) {
			k--; 
			node *u=q.top().now;
			LL base=q.top().base;
			q.pop();
			if(!k) {cout<<dis[2]+base+u->val.first<<'\n'; return;}
			if(u->lc) q.push(data(u->lc,base));
			if(u->rc) q.push(data(u->rc,base));
			if(rt[u->val.second])
				q.push(data(rt[u->val.second],base+u->val.first));
		}
	}
}
using KSP::add;
using KSP::tot;

int dfn[N],ord[N],ind;
inline void pre(int x,int lim,int f=0) {
	dfn[x]=++ind; 
	ord[ind]=x;
	sze[x]=1;
	for(auto v:edge[x])
		if((v^f) && dep[v]>lim)
			pre(v,lim,x), sze[x]+=sze[v];
}

         
inline void build(int x) {
	ind=0; pre(x,dep[x]); 
	add(1,tot+1,0);
	for(int i=1;i<=ind;i++) {
		int u=ord[i], sz=sze[u];
		add(tot+dfn[u],(dfn[u]==ind) ? KSP::des : (tot+dfn[u]+1),a[u]);
		if(u!=x) add(tot+dfn[u],(dfn[u]+sz>ind) ? KSP::des : (tot+dfn[u]+sz),0);
	} tot+=ind;
}

int main() {
	n=rd(), k=rd();
	for(int i=1;i<n;i++) {
		int x=rd(), y=rd();
		edge[x].push_back(y);
		edge[y].push_back(x);
	}
	for(int i=1;i<=n;i++) a[i]=rd();
	
	mx=total=n;
	calcG(1,0); 
	solve(G,0);
	
	for(int i=1;i<=n;i++) build(i);
	KSP::solve();
}
发布了553 篇原创文章 · 获赞 227 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/86365537