luogu P3623 [APIO2008]免费道路

版权声明:本文为博主原创文章,未经博主允许不得转载。 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 ;
}

猜你喜欢

转载自blog.csdn.net/qq_42369449/article/details/82806738