最小生成树
Boruvka’s Algorit
给每个点先找一个最小的边染色一定是若干个树,每个树里有一个重边每个联通块缩点n至少/2做log次
对这个问题套用Boruvka算法会变成什么?每个点有一个颜色,询问每个点和不同颜色的边权最小值同样用扫描线加线段树处理这个事情, 不过怎么处理不同颜色这个限制,记录最优值的时候顺便记录一个和最优值不同颜色的次优值时间复杂度nlog^2n, 要卡常
#include<bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e5+10;
const ll INF=1ll<<60;
struct event{int l,r,v;};
vector<event> s[MAXN];
ll tag[MAXN<<2];
int n,q,w,f[MAXN];
struct node{ll val;int id,col;}
seg[MAXN<<2][2],mp[MAXN],init;
int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);}
#define mid ((l+r)>>1)
#define ls k<<1
#define rs k<<1|1
#define lc k<<1,l,mid
#define rc k<<1|1,mid+1,r
void upd(int k,node t)
{
if(t.val<seg[k][0].val)
{
if(t.col!=seg[k][0].col)
seg[k][1]=seg[k][0];
seg[k][0]=t;
}
else if(t.val<seg[k][1].val&&t.col!=seg[k][0].col)
seg[k][1]=t;
}
void pushup(int k)
{
seg[k][0].val=seg[k][1].val=INF;
upd(k,seg[ls][0]);upd(k,seg[ls][1]);
upd(k,seg[rs][0]);upd(k,seg[rs][1]);
}
void pushdown(int k)
{
seg[ls][0].val+=tag[k];
seg[ls][1].val+=tag[k];
seg[rs][0].val+=tag[k];
seg[rs][1].val+=tag[k];
tag[ls]+=tag[k];tag[rs]+=tag[k];tag[k]=0;
}
void build(int k,int l,int r)
{
tag[k]=0;
if(l==r)
{seg[k][0]=(node){0,l,find(l)};seg[k][1]=init;return;}
build(lc);build(rc);pushup(k);
}
void update(int a,int b,int k,int l,int r,int val)
{
if(a<=l&&r<=b)
{tag[k]+=val;seg[k][0].val+=val;seg[k][1].val+=val;return;}
if(tag[k]) pushdown(k);
if(a<=mid) update(a,b,lc,val);
if(b>mid) update(a,b,rc,val);
pushup(k);
}
int main()
{
scanf("%d%d",&n,&q);
init=(node){INF,0,0};
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=q;i++)
{
int x1,y1,x2,y2,w;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&w);
s[x1].pb((event){x2,y2,w});s[y1+1].pb((event){x2,y2,-w});
s[x2].pb((event){x1,y1,w});s[y2+1].pb((event){x1,y1,-w});
}
int cur=0;ll res=0;
while(cur<n-1)
{
build(1,1,n);
for(int i=1;i<=n;i++) mp[i]=init;
for(int i=1;i<=n;i++)
{
for(auto j:s[i])
update(j.l,j.r,1,1,n,j.v);
int col=find(i);
node tmp=seg[1][col==seg[1][0].col];
if(tmp.val<mp[col].val) mp[col]=tmp;
}
for(int i=1;i<=n;i++)
{
if(!mp[i].id) continue;
int fx=find(i),fy=find(mp[i].id);
if(fx!=fy) f[fx]=fy,res+=mp[i].val,cur++;
}
}
printf("%lld\n",res);
return 0;
}