2012 年国家集训队互测 Tree
给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有 need条白色边的生成树。题目保证有解
感觉不是很懂这道题所谓用need代还cnt的做法
反正bzoj数据水怎么都是对的
#include<bits/stdc++.h> #define re return #define ll long long #define inc(i,l,r) for(int i=l;i<=r;++i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } const int maxn=50005,maxm=100005; int n,m,sum,need,ans,hd[maxn],fa[maxn]; struct node{ int fr,to,val,flag; bool operator<(node a)const { if(val==a.val)re flag<a.flag; re val<a.val; } }e[maxm]; inline int find(int x) { re x==fa[x]?x:fa[x]=find(fa[x]); } inline int vivi(int x) { inc(i,1,m)if(!e[i].flag)e[i].val+=x; inc(i,1,n)fa[i]=i; sort(e+1,e+m+1); int cnt=0,tot=0; sum=0; inc(i,1,m) { int f1=find(e[i].fr),f2=find(e[i].to); if(f1!=f2) { ++tot; sum+=e[i].val; if(!e[i].flag) ++cnt; fa[f1]=f2; if(tot==n-1)break; } } inc(i,1,m) if(!e[i].flag) e[i].val-=x; if(cnt<need)re 0; ans=sum-cnt*x;
//但是如果是need的话,不是与原来在边权和不等吗 re 1; } int main() { freopen("in.txt","r",stdin); rd(n),rd(m);rd(need); inc(i,1,m) { rd(e[i].fr);rd(e[i].to); ++e[i].fr;++e[i].to; rd(e[i].val);rd(e[i].flag); } int l=-100,r=100; while(l<=r) { int mid=(l+r)>>1; if(vivi(mid)) l=mid+1; else r=mid-1; } printf("%d",ans); re 0; }