HT-65-NOI-T2 题解
题意
设一棵树的权值为
题解
显然给定
此时需要解决两种边分别选择
考虑用斜率为
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+10;
const int P=1e9+1e7;
const ll inf=1e18+1e17;
int n,m,ct,c,a[N],f[N],s[N]; ll res,ans=-inf;
struct edg{int u,v,w,f;}e[N],E[N];
bool cmp(edg ta,edg tb)
{
if(ta.w==tb.w) return ta.f<tb.f;
return ta.w>tb.w;
}
int finds(int x) {return f[x]==x?x:f[x]=finds(f[x]);}
bool merg(int x,int y)
{
x=finds(x),y=finds(y);
if(x==y) return false;
s[y]+=s[x],f[x]=y; return true;
}
int chk(int x,int k)
{
for(int i=1;i<=m;i++) e[i]=E[i],e[i].f=(e[i].w<=x),e[i].w=abs(e[i].w-x)-e[i].f*k;
sort(e+1,e+1+m,cmp),res=0; int C=0,cx=0;
for(int i=1;i<=n;i++) f[i]=i,s[i]=1;
for(int i=1;i<=m;i++)
{
if(merg(e[i].u,e[i].v)) C++,cx+=e[i].f,res+=e[i].w;
if(C==c*2) break;
}
return cx;
}
ll check(int x)
{
int l=-P,r=P,rk=P+1;
while(l<=r)
{
int mid=((l+r)>>1),t=chk(x,mid);
if(t<=c) rk=mid,r=mid-1;
else l=mid+1;
}
if(rk==P+1||chk(x,rk-1)<c) return -inf;
chk(x,rk); return res+1ll*c*rk;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m,c=((n-1)>>1);
for(int i=1;i<=m;i++) cin>>E[i].u>>E[i].v>>E[i].w,a[i]=E[i].w;
sort(a+1,a+1+m),ct=unique(a+1,a+1+m)-a-1;
for(int i=1;i<=ct;i++) ans=max(ans,check(a[i]));
cout<<ans;
return 0;
}
观察上述代码,注意到同时给所有边加上一个值
此时要求的问题如下:原图中每条边产生白边
此时显然存在一个
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int N=5e5+10;
const int P=1e9+1e7;
const ll inf=1e18+1e17;
int n,m,k,c,a[N],f[N],s[N],C,cx; ll res,ans=-inf;
struct edg{int u,v,w;}e[N],E[N];
bool cmp(edg ta,edg tb) {return ta.w>tb.w;}
int finds(int x) {return f[x]==x?x:f[x]=finds(f[x]);}
bool merg(int x,int y)
{
x=finds(x),y=finds(y);
if(x==y) return false;
s[y]+=s[x],f[x]=y; return true;
}
void add(edg te,bool f)
{
if(C==c*2) return;
if(merg(te.u,te.v)) C++,cx+=f,res+=te.w;
}
void chk(ll X)
{
for(int i=1;i<=m;i++) e[i]=E[m-i+1],e[i].w=X-e[i].w;
res=0,C=0,cx=0; int pa=1,pb=1;
for(int i=1;i<=n;i++) f[i]=i,s[i]=1;
while(pa<=m&&pb<=m)
{
if(e[pa].w>E[pb].w) add(e[pa],1),pa++;
else add(E[pb],0),pb++;
}
while(pa<=m) add(e[pa],1),pa++;
while(pb<=m) add(E[pb],0),pb++;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m,c=((n-1)>>1);
for(int i=1;i<=m;i++) cin>>E[i].u>>E[i].v>>E[i].w;
sort(E+1,E+1+m,cmp);
ll l=-P,r=2*P,rk=-P-1;
while(l<=r)
{
ll mid=((l+r)>>1); chk(mid);
if(cx<=c) rk=mid,l=mid+1;
else r=mid-1;
}
chk(rk),cout<<res-c*rk;
return 0;
}