bzoj3624(铺黑白路)(并查集维护)

题意网上自己随便找,绝对是找的到的。

题解:(白边表示鹅卵石路,黑边表示水泥路)这道题的解法,先考虑将黑边所有都先连起来,组成一个又一个的联通块,然后用白边去连,

如果可以联通的话,就用白边去代替黑边,必要的白边(就是维护联通性的白边必须要先保证),然后再去代替,直到k条边满足,不满足则输出NO

然后就再用黑边去连,记录,反正是Special Judge所以顺序没有关系,就好了。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 typedef long long ll;
 9 const int INF=1e9+7,NN=20007,MM=100007;
10 
11 int n,m,K,top;
12 int fa[NN];
13 int u[MM],v[MM],c[MM];
14 int au[NN],av[NN],ac[NN];
15 bool mark[MM];
16 int num[2];
17 
18 int find(int num)
19 {
20     if (fa[num]==num) return num;
21     else fa[num]=find(fa[num]);
22     return fa[num];
23 }
24 void solve(bool typ,int up)
25 {
26     for(int i=1;i<=m;i++)
27         if(c[i]==typ&&num[typ]<up)
28         {
29             int p=find(u[i]),q=find(v[i]);
30             if(p!=q)
31             {
32                 fa[p]=q;
33                 au[++top]=u[i],av[top]=v[i],ac[top]=c[i];
34                 mark[i]=1;
35                 num[typ]++;
36             }
37         }
38 }
39 void init()
40 {
41     memset(mark,0,sizeof(mark));
42     scanf("%d%d%d",&n,&m,&K);
43     for(int i=1;i<=m;i++) 
44         scanf("%d%d%d",&u[i],&v[i],&c[i]);
45     for(int i=1;i<=n;i++)
46         fa[i]=i;
47 }
48 int main()
49 {
50     init();
51     
52     num[0]=num[1]=0;
53     solve(1,INF),solve(0,INF);
54     if(num[1]+num[0]!=n-1||num[0]>K)
55     {
56         puts("no solution\n");
57         return 0;
58     }//及如果需要>k条鹅卵石路将各个块连起来,或者需要多余n-1条边
59     
60     top=num[0]=num[1]=0;//然后用鹅卵石重新铺 
61     for(int i=1;i<=n;i++)
62         fa[i]=i;
63     for(int i=1;i<=m;i++)
64         if(c[i]==0&&mark[i])
65         {
66             int p=find(u[i]),q=find(v[i]);
67             if(p!=q)
68             {
69                 num[0]++;fa[p]=q;
70                 au[++top]=u[i];av[top]=v[i];ac[top]=c[i];
71             }
72         }//必要的先铺满
73     solve(0,K),solve(1,INF);//然后再不必要鹅卵石的取铺,然后再用水泥路取铺就可以了。 
74     if(num[0]<K)
75     {
76         puts("no solution");
77         return 0;
78     }
79     for(int i=1;i<=top;i++)
80         printf("%d %d %d\n",au[i],av[i],ac[i]);
81 }

 

posted @ 2017-08-25 21:01  Kaiser-  阅读(230)  评论(0编辑  收藏  举报