For a graph of N vertices and m edges, each edge belongs to Company A or Company B. A minimum spanning tree is required, with the condition that the number of edges belonging to Company A is K.
This is a clever practice.
The minimum generation tree is required, but there are certain restrictions. Search and greedy are obviously not correct.
If we can find a reasonable control method so that the number of Edge Nodes of Company A can be controlled in the MST process, the problem will be solved.
Therefore, we can manually add certain weights to the side of Company A, so that some of them have to exit the MST selection range.
If the number of edges in Company A in the MST is greater than K, the weight is increased. When the number of edges is less than K, the weight is negative.
Therefore, by using the binary edge weight, we can obtain the Edge Number of Company A contained in the MST to gradually approach K. At this time, the answer is recorded. because there must be a solution, it must eventually be the answer.
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int maxm=100010;const int maxn=50010;struct node{ int u,v,w,ty;}e[maxm];int r[maxn],n,m,k,ret,telecom;bool cmpw(node a,node b){ if(a.w!=b.w) return a.w<b.w; return a.ty<b.ty;}int root(int a){ if(r[a]==-1) return a; return r[a]=root(r[a]);}bool kru(int x){ for(int i=0;i<m;i++) if(e[i].ty==0) e[i].w+=x; sort(e,e+m,cmpw); memset(r,-1,sizeof r); int edge=0;telecom=n-1;ret=0; for(int i=0;i<m;i++) { int ra=root(e[i].u); int rb=root(e[i].v); if(ra!=rb) { r[ra]=rb; ret+=e[i].w; telecom-=e[i].ty; if(++edge==n-1) break; } } for(int i=0;i<m;i++) if(e[i].ty==0) e[i].w-=x; return telecom>=k;}int main(){ int cas=1; while(~scanf("%d%d%d",&n,&m,&k)) { for(int i=0;i<m;i++) scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].w,&e[i].ty); int l=-100,r=100,mid,ans=0x3f3f3f3f; while(l<=r) { mid=(l+r)/2; if(kru(mid)) l=mid+1,ans=ret-mid*k; else r=mid-1; } printf("Case %d: %d\n",cas++,ans); } return 0;}
Hdustm3 two famous companies --- binary + MST