【校內模擬】小B的圖(貪心)(MST)(LCT)

簡要題意:

給一張圖,有兩種邊,第一種的權值爲 v+xv+x,其中 xx 是變量,第二種的權值爲 vxv-x。 現在給出若干 xx 的值,請你求出MST的大小。

分別只保留兩種邊的圖仍然連通。


題解:

由於本身兩種圖是連通的,所以在新MST上的邊只可能是原來兩種邊的MST中的邊。

v+xv+x 拿來做MST,建立LCT。考慮用 vxv-x 來替換。

注意替換順序並不是按照 vxv-x 中的 vv 的大小,而是它什麼時候權值比被它換下的邊優。


代碼:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const

namespace IO{
	inline char gc(){
		static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}template<typename T>T get_integer(){
		char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
		while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x; 
	}inline int gi(){return get_integer<int>();}
	char obuf[10000007],*oh=obuf;
	template<typename T>void print(T a,char c=' '){
		static char ch[23];int tl=0;
		if(a<0)*oh++='-',a=-a;
		do ch[++tl]=a%10; while(a/=10);
		while(tl)*oh++=ch[tl--]^48;*oh++=c;
	}struct obuf_flusher{~obuf_flusher(){fwrite(obuf,1,oh-obuf,stdout);}}Flusher;
}using namespace IO;

using std::cerr;
using std::cout;

cs int N=1e5+7,M=2e5+7;

int n,Q,a,b; 

struct edge{int u,v,w;};
bool cmp(cs edge &a,cs edge &b){
	return a.w<b.w;
}
edge A[M],B[M];

int vl[N+M],INF;
namespace LCT{

cs int N=3e5+7;

int mxp[N],fa[N];
int son[N][2];
bool rev[N];

inline bool isrt(int u){return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;}
inline bool get(int u){return son[fa[u]][1]==u;}
inline void push_up(int u){
	mxp[u]=u;
	if(vl[mxp[u]]<vl[mxp[son[u][0]]])mxp[u]=mxp[son[u][0]];
	if(vl[mxp[u]]<vl[mxp[son[u][1]]])mxp[u]=mxp[son[u][1]];
}inline void push_dn(int u){
	if(rev[u]){
		std::swap(son[u][0],son[u][1]);
		rev[son[u][0]]^=1;
		rev[son[u][1]]^=1;
		rev[u]=0;
	}
}inline void Rotate(int u){
	int p=fa[u],pp=fa[p],d=get(u);
	if(!isrt(p))son[pp][get(p)]=u;
	son[p][d]=son[u][!d],son[u][!d]=p;
	fa[p]=u,fa[u]=pp,fa[son[p][d]]=p;
	push_up(p);push_up(u);
}void Splay(int u){
	static int q[N],qn;q[qn=1]=u;
	for(int re p=u;!isrt(p);p=fa[p])q[++qn]=fa[p];
	for(int re i=qn;i;--i)push_dn(q[i]);
	for(int re p=fa[u];!isrt(u);Rotate(u),p=fa[u])
	if(!isrt(p))Rotate(get(u)==get(p)?p:u);push_up(u); 
}void access(int u){
	for(int re ch=0;u;u=fa[ch=u]){
		Splay(u);son[u][1]=ch;push_up(u);
	}
}void makert(int u){access(u);Splay(u),rev[u]^=1;}
void link(int u,int v){
	makert(u);fa[u]=v;
}void cut(int u,int v){
	makert(u);access(v);Splay(v);
	fa[son[v][0]]=0,son[v][0]=0,push_up(v);
}

}

int bel[N];
inline int gf(int u){
	while(u!=bel[u])u=bel[u]=bel[bel[u]];
	return u;
}

int tot;
struct func{ll k,b,ps;}f[N];
bool cmp_func(cs func &a,cs func &b){
	return a.ps<b.ps;
}

void Main(){
	n=gi(),a=gi(),b=gi(),Q=gi();
	memset(vl,128,sizeof vl);INF=-vl[0];
	for(int re i=1;i<=n+a;++i)LCT::mxp[i]=i;
	for(int re i=1;i<=a;++i)
		A[i].u=gi(),A[i].v=gi(),A[i].w=gi();
	for(int re i=1;i<=b;++i)
		B[i].u=gi(),B[i].v=gi(),B[i].w=gi();
	std::sort(A+1,A+a+1,cmp);
	std::sort(B+1,B+b+1,cmp);
	for(int re i=1;i<=n;++i)bel[i]=i;
	f[tot=1].ps=-INF;
	for(int re i=1;i<=a;++i){
		vl[n+i]=A[i].w;
		int u=A[i].u,v=A[i].v;
		if(gf(u)!=gf(v)){
			LCT::link(u,i+n);
			LCT::link(v,i+n);
			bel[gf(u)]=gf(v);
			f[1].b+=A[i].w;
		}
	}
	for(int re i=1;i<=n;++i)bel[i]=i;
	for(int re i=1;i<=b;++i){
		int u=B[i].u,v=B[i].v;
		if(gf(u)==gf(v))continue;
		bel[gf(u)]=gf(v);
		LCT::makert(v);
		LCT::access(u);
		LCT::Splay(u);
		int t=LCT::mxp[u];
		ll tmp=B[i].w-vl[t];
		f[++tot].ps=tmp/2+((tmp&1)&&tmp>0);
		f[tot].b=tmp;
		LCT::cut(t,A[t-n].u);
		LCT::cut(t,A[t-n].v);
		LCT::link(u,v);
	}
	std::sort(f+1,f+tot+1,cmp_func);
	f[1].k=n-1;
	for(int re i=2;i<=tot;++i)
		f[i].b+=f[i-1].b,f[i].k=f[i-1].k-2;
	while(Q--){
		ll v=gi();int l=1,r=tot,mid;
		while(l<r)
			f[mid=(l+r+1)>>1].ps<=v?(l=mid):(r=mid-1);
		print(f[l].k*v+f[l].b,'\n');
	}
}

#undef zxyoi
inline void file(){
#ifdef zxyoi
	freopen("graph.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
	freopen("graph.in","r",stdin);
	freopen("graph.out","w",stdout);
#endif
#endif
}
signed main(){file();Main();return 0;}
發佈了993 篇原創文章 · 獲贊 374 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章