给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
题目保证有解。
标签:nbsp 方案 cdb pac sam 表示 turn etc 端点
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int N=100050; struct Edge{ int from,to,val,col; }edge[N]; int from[N],to[N],val[N],col[N]; int fa[N]; int n,m,Need,ans,tot,cnt; inline void read(int &s){ int flag=1;s=0;char ch=getchar(); while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)flag=-1;ch=getchar();} while(ch>=‘0‘ && ch<=‘9‘){s=s*10+ch-‘0‘;ch=getchar();} s*=flag; } inline bool operator < (const Edge &a,const Edge &b){return a.val==b.val ? a.col<b.col : a.val<b.val;} int find(int x){return x==fa[x] ? fa[x] : fa[x]=find(fa[x]);} bool check(int x){ tot=cnt=0; for(int i=1;i<=n;++i)fa[i]=i; for(int i=1;i<=m;++i){ edge[i].from=from[i];edge[i].to=to[i];edge[i].val=val[i];edge[i].col=col[i]; if(!col[i])edge[i].val+=x; } sort(edge+1,edge+m+1); for(int i=1;i<=m;++i){ int fx=find(edge[i].from),fy=find(edge[i].to); if(fx!=fy){ fa[fx]=fy; tot+=edge[i].val; if(!edge[i].col)++cnt; } } return cnt>=Need; } int main(){ read(n);read(m);read(Need); for(int i=1;i<=m;++i){ read(from[i]);read(to[i]);read(val[i]);read(col[i]); ++from[i];++to[i]; } int l=-105,r=105; while(l<=r){ int mid=(l+r)>>1; if(check(mid))l=mid+1,ans=tot-Need*mid; else r=mid-1; } printf("%d\n",ans); return 0; }
标签:nbsp 方案 cdb pac sam 表示 turn etc 端点
原文地址:http://www.cnblogs.com/cygol/p/6746410.html