Long live the National Day!!!!!
"The main topic"
Given an untyped graph, there are two types of edges that are 0 and 1. Find a minimum spanning tree so that side 0 has k bars.
Ideas
Run two times Kruskal.
The first time to select the Edge 1, and then determine which side 0 is not connected, then these side 0 must be selected. If you have to select an edge 0 greater than K, then the direct output is no solution.
The second time first merge then must select the Edge 0, and then in the remaining side 0 left or right there is no connected to the selection. If you select all of the back 0 of the number is still not to K, then the direct output of no solution.
Cut down to the common Kruskal method to merge the side 1.
1#include <iostream>2#include <cstdio>3#include <algorithm>4#include <cstring>5#include <vector>6 using namespacestd;7 Const intmaxn=20000+ -;8 Const intmaxm=100000+ -;9 structEdgeTen { One intu,v; A }EDGE[MAXM]; - intn,m,k; - intVIS[MAXM]; the intL,r; - intFA[MAXN],H[MAXN]; -vector<int>Mustchoose; - + voidInitset () { for(intI=1; i<=n;i++) fa[i]=i,h[i]=1;} - + intFindintx) A { at intR=x; - while(fa[r]!=r) r=Fa[r]; - while(fa[x]!=R) - { - inttmp=Fa[x]; -fa[x]=R; inx=Fa[x]; - } to returnR; + } - the voidUnionset (intAintb) * { $ if(h[a]>=H[b])Panax Notoginseng { -fa[b]=A; the if(H[a]==h[b]) h[a]++; + } A Elsefa[a]=b; the } + - voidInit () $ { $scanf"%d%d%d",&n,&m,&k); -L=0, r=m+1; - for(intI=1; i<=m;i++) the { - intu,v,c;Wuyiscanf"%d%d%d",&u,&v,&c); the if(c) edge[++l]=(Edge) {u,v}; - Elseedge[--r]=(Edge) {u,v}; Wu } - } About $ voidSolve () - { - intt=0; - Initset (); A for(intI=1; i<=m;i++) + { the intFa=find (edge[i].u), fb=find (EDGE[I].V); - if(fa!=FB) $ { the Unionset (FA,FB); the if(i>=R) the { thevis[i]=1; -t++; in Mustchoose.push_back (i); the } the } About } the if(t>k) the { thePuts"No solution"); + return; - } the //Find the Cobblestone road you have to chooseBayi the Initset (); the for(intI=0; I<mustchoose.size (); i++) - { - intFa=find (edge[mustchoose[i]].u), fb=find (EDGE[MUSTCHOOSE[I]].V); the Unionset (FA,FB); the } the for(inti=r;i<=m;i++) the if(T<k &&!)Vis[i]) - { the intFa=find (edge[i].u), fb=find (EDGE[I].V); the if(fa!=FB) the {94 Unionset (FA,FB); thevis[i]=1; thet++; the }98 } About if(t<k) - {101Puts"No solution");102 return;103 }104 //first select the cobblestone path you want, and then fill it with other cobblestone paths the 106 for(intI=1; i<=l;i++)107 {108 intFa=find (edge[i].u), fb=find (EDGE[I].V);109 if(fa!=FB) the {111 Unionset (FA,FB); thevis[i]=1;113 } the } the for(intI=1; i<=l;i++)if(Vis[i]) printf ("%d%d%d\n", EDGE[I].U,EDGE[I].V,1); the for(inti=r;i<=m;i++)if(Vis[i]) printf ("%d%d%d\n", EDGE[I].U,EDGE[I].V,0);117 }118 119 intMain () - {121 init ();122 solve ();123}
"Kruskal+ greedy thought" bzoj3624-[apio2008] Free Road