tree
内存限制:512 MiB 时间限制:3000 ms 标准输入输出
题目类型:传统 评测方式:文本比较
题目描述
输入格式
输出格式
样例
数据范围与提示
也是一个做法比较玄学的题
二分答案,考虑我们往白边上加值或者减值,那么就会对应的少选白边或者少选黑边
那么如果当前 白边+mid如果kuskal选择白边比need多就继续往上面加值,如果选择白边比need少就往下减值
因为kuskal保证图一定连通,并且代价最小。所以保证了正确性
#include<bits/stdc++.h> #define ll long long #define A 10000000 using namespace std; struct edge{ ll x,y,z,id; ll flag; }e[A]; ll n,m,need,fa[A],zong,ans,end[A]; inline ll read() { ll f=1,x=0;char c=getchar(); while(!isdigit(c)){if(c=='-') f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();} return f*x; } ll find(ll x) { if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } void hebing(ll x,ll y) { x=find(x),y=find(y); if(x!=y) fa[y]=x; } bool cmp(edge a,edge b){return (a.z==b.z)?(a.flag<b.flag):(a.z<b.z);} inline void kuskar(ll mid) { for(ll i=0;i<=n;i++) fa[i]=i; zong=0,ans=0; for(ll i=1;i<=m;i++) if(!e[i].flag) e[i].z+=mid; sort(e+1,e+m+1,cmp); for(ll i=1;i<=m;i++) { if(find(e[i].x)!=find(e[i].y)) { if(!e[i].flag) zong++; hebing(e[i].x,e[i].y); ans+=e[i].z; } } for(ll i=1;i<=m;i++) if(!e[i].flag) e[i].z-=mid; } int main() { ll tot=0; n=read(),m=read(),need=read(); for(ll i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].z=read(),e[i].flag=read(); ll l=-100,r=100; while(l<=r) { ll mid=(l+r)>>1; kuskar(mid); if(zong>=need) l=mid+1,tot=ans-need*mid; else r=mid-1; } cout<<tot<<endl; }