[BZOJ]3624: [Apio2008]免费道路 最小生成树

来源:互联网 发布:jmeter 安装mac版 编辑:程序博客网 时间:2024/06/12 22:01

Description
这里写图片描述

题解:

乱搞,首先求出哪些鹅卵石路是必须要选的,方法是先用水泥路连,用完水泥路之后用的鹅卵石路就是必须要选的。然后若不足k条,则随便选几条鹅卵石路,最后随便选几条水泥路就好了。还要判断一下几个无解的情况。

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int Maxn=20010;const int Maxm=100010;struct Edge{int x,y,c;}e[Maxm],e1[Maxm],Ans[Maxn];bool cmp(Edge a,Edge b){return a.c>b.c;}int n,m,k,f[Maxn],l=0,num=0,la=0;int Find(int x){return f[x]==x?x:f[x]=Find(f[x]);}bool mark[Maxm];int main(){    scanf("%d%d%d",&n,&m,&k);    for(int i=1;i<=m;i++)    scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].c);    for(int i=1;i<=n;i++)f[i]=i;    sort(e+1,e+1+m,cmp);    for(int i=1;i<=m;i++)    {        int fx=Find(e[i].x),fy=Find(e[i].y);        if(fx!=fy)        {            f[fx]=fy;            if(!e[i].c)e1[++l]=e[i],e1[l].c=i;            num++;        }    }    if(l>k||num!=n-1){puts("no solution");return 0;}    for(int i=1;i<=n;i++)f[i]=i;    for(int i=1;i<=l;i++)//必须用的边     {        mark[e1[i].c]=true;Ans[++la]=e[e1[i].c];        int fx=Find(e1[i].x),fy=Find(e1[i].y);        if(fx!=fy)f[fx]=fy;    }    k-=l;    for(int i=m;k;i--)//随便几条鹅卵石路     if(!mark[i])    {        int fx=Find(e[i].x),fy=Find(e[i].y);        if(fx!=fy)f[fx]=fy,k--,Ans[++la]=e[i];    }    for(int i=1;i<=m;i++)//水泥路     {        int fx=Find(e[i].x),fy=Find(e[i].y);        if(fx!=fy)f[fx]=fy,Ans[++la]=e[i];    }    for(int i=1;i<=la;i++)    printf("%d %d %d\n",Ans[i].x,Ans[i].y,Ans[i].c);}
原创粉丝点击