给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
题目保证有解。
标签:
给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
题目保证有解。
第一行V,E,need分别表示点数,边数和需要的白色边数。
接下来E行
每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。
一行表示所求生成树的边权和。
数据规模和约定
0:V<=10
1,2,3:V<=15
0,..,19:V<=50000,E<=100000
所有数据边权为[1,100]中的正整数。
#include<cstdio> #include<algorithm> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } struct ed{int x,y,z,color;}e[100010]; struct bian{int x,y,z,mrk;}a[100010]; inline bool operator<(const bian &a,const bian &b){return a.z<b.z||a.z==b.z&&a.mrk>b.mrk;} int n,m,k,ans,tot,sum,tt; int fa[100010]; inline int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);} inline void jud(int mid) { tot=sum=0; for (int i=1;i<=n;i++)fa[i]=i; for (int i=1;i<=m;i++) { a[i].x=e[i].x; a[i].y=e[i].y; a[i].z=e[i].z+(e[i].color*mid); a[i].mrk=e[i].color; } sort(a+1,a+m+1); for (int i=1;i<=m;i++) { int fx=getfa(a[i].x),fy=getfa(a[i].y); if (fx==fy)continue; if (a[i].mrk)tot++; fa[fx]=fy; sum+=a[i].z; } } int main() { n=read();m=read();k=read(); for (int i=1;i<=m;i++) { e[i].x=read()+1; e[i].y=read()+1; e[i].z=read(); e[i].color=read()^1; if (e[i].color)tt++; } int l=-105,r=105; while (l<=r) { int mid=(l+r)>>1; jud(mid); if (tot>=k){ans=sum-k*mid;l=mid+1;} else r=mid-1; } printf("%d\n",ans); return 0; }
标签:
原文地址:http://www.cnblogs.com/zhber/p/4254745.html