已经 AC,但是有个地方不清楚。
#include<bits/stdc++.h>
using namespace std;
struct edge
{
int x,y,z;
edge() {}
edge(int x, int y, int z) : x(x), y(y), z(z) {}
};
struct dsu
{
int fa[50100];
void clear(int n) { for(int i=0; i<=n; i++) fa[i]=i; }
int find(int x) { return x==fa[x] ? fa[x] : fa[x]=find(fa[x]); }
bool merge(int x, int y)
{
int fx=find(x),fy=find(y);
if(fx==fy) return 0;
fa[fy]=fx;
return 1;
}
};
vector<edge> v1,v2;
dsu u;
int n,m,t;
long long ans;
bool check(int k)
{
int ans=0;
int i=0,j=0;
u.clear(n);
while(i<v1.size()&&j<v2.size())
{
if(v1[i].z<v2[j].z+k)
u.merge(v1[i].x, v1[i].y), ++i;
else
ans+=u.merge(v2[j].x, v2[j].y), ++j;
}
while(j<v2.size())
ans+=u.merge(v2[j].x, v2[j].y), ++j;
return ans<t;
}
int erfen(int l, int r)
{
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid+1))
r=mid;
else
l=mid+1;
}
return l;
}
bool cmp(const edge &a, const edge &b)
{
return a.z<b.z;
}
int main()
{
cin>>n>>m>>t;
for(int i=1; i<=m; i++)
{
int x,y,z,c;
scanf("%d%d%d%d", &x, &y, &z, &c);
if(c) v1.emplace_back(x, y, z);
else v2.emplace_back(x, y, z);
}
sort(v1.begin(), v1.end(), cmp);
sort(v2.begin(), v2.end(), cmp);
int k=erfen(-100, 100);
u.clear(n);
int i=0,j=0;
while(i<v1.size()&&j<v2.size())
{
if(v1[i].z<v2[j].z+k)
ans+=v1[i].z*u.merge(v1[i].x, v1[i].y), ++i; //
else
ans+=(v2[j].z+k)*u.merge(v2[j].x, v2[j].y), ++j;
}
while(i<v1.size())
ans+=v1[i].z*u.merge(v1[i].x, v1[i].y), ++i; //
while(j<v2.size())
ans+=(v2[j].z+k)*u.merge(v2[j].x, v2[j].y), ++j;
cout<<ans-k*t; //
// 就这几个地方,先是加上 k,后面再减掉,正常来说去掉也是可以的,
// 但是去掉 40pts,应该是选的个数不是恰好 need 个,请问这是为什么?
return 0;
}