版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_42369449/article/details/82806738
算法:kruskal 、贪心
难度:(NOIP)
注意:*细节多*
首先,你什么也不会发现,因为它很裸,用到一点贪心的知识,先拿出所有水泥路来玩Kruskal,如果形成了一棵树,那就形成一棵树吧,反正有SPJ,如果没有形成一棵树,就拿出鹅卵石路往树上拍,并且把这些鹅卵石路标记上,因为它们是使图联通必不可少的边,累加k。然后memset(fa),再次跑Kruskal,首先把必须需要的鹅卵石路加进去,然后再往上加不是必须需要的鹅卵石路,直到k值达到要求,就跳出,最后如果图没有联通,就添加水泥路,并记录,输出即可!
*注意:要在很多地方判断这时是否合法,并且及时输出“no solution”!!!不然,你会WA的很惨*
代码如下(这个代码A不了......)
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#define ll long long
#define maxn 100005
using namespace std;
struct node
{
int u,v,w;
}edg[maxn];
int fa[maxn];
int findf(int x)
{
if(fa[x]==x)
{
return x;
}
return fa[x]=findf(fa[x]);
}
int cmp1(node x,node y)
{
return x.w>y.w;
}
int cmp2(node x,node y)
{
return x.w<y.w;
}
int vis[maxn];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i = 1;i <= n;i++)
{
fa[i]=i;
}
int ns=0;
for(int i = 1;i <= m;i++)
{
scanf("%d%d%d",&edg[i].u,&edg[i].v,&edg[i].w);
if(edg[i].w==0) ns++;
}
if(ns<k)
{
printf("no solution");
exit(0);
}
sort(edg+1,edg+1+m,cmp1);
int ctt=0;
for(int i = 1;i <= m;i++)
{
if(edg[i].w==0) continue;
int t1=findf(edg[i].u);
int t2=findf(edg[i].v);
if(t1==t2)
{
continue;
}else
{
fa[t1]=t2;
ctt++;
}
}
int num=0;
for(int i = 1;i <= m;i++)
{
if(edg[i].w==1) continue;
int t1=findf(edg[i].u);
int t2=findf(edg[i].v);
if(t1==t2)
{
continue;
}else
{
vis[i]=1;
fa[t1]=t2;
ctt++;
num++;
if(ctt == n - 1) break;
}
}
if(num>k||ctt<n-1)
{
printf("no solution");
exit(0);
}
for(int i = 1;i <= n;i++)
{
fa[i]=i;
}
sort(edg+1,edg+1+m,cmp2);
ctt=0;
for(int i = 1;i <= m;i++)
{
if(vis[i]==1)
{
int t1=findf(edg[i].u);
int t2=findf(edg[i].v);
if(t1==t2)
{
continue;
}else
{
fa[t1]=t2;
ctt++;
}
}
}
if(ctt>k)
{
printf("no solution");
exit(0);
}
for(int i = 1;i <= m;i++)
{
if(ctt==k) break;
if(vis[i]==0&&edg[i].w==0)
{
int t1=findf(edg[i].u);
int t2=findf(edg[i].v);
if(t1==t2)
{
continue;
}else
{
vis[i]=1;
fa[t1]=t2;
ctt++;
}
}
}
if(ctt<k)
{
puts("no solution");
exit(0);
}
for(int i = 1;i <= m;i++)
{
if(vis[i]==0&&edg[i].w==1)
{
int t1=findf(edg[i].u);
int t2=findf(edg[i].v);
if(t1==t2)
{
continue;
}else
{
vis[i]=1;
fa[t1]=t2;
ctt++;
}
}
}
if(ctt<n-1)
{
printf("no solution");
exit(0);
}
for(int i = 1;i <= m;i++)
{
if(vis[i])
{
printf("%d %d %d\n", edg[i].u,edg[i].v,edg[i].w);
}
}
return 0 ;
}