BZOJ 3624 免费道路

Posted ziliuziliu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3624 免费道路相关的知识,希望对你有一定的参考价值。

第一反应:这不先0后1做并查集就行了吗?

然后WA了。。。

哦。。。。啊?哦。。。233

如果按顺序做并查集,有些0的边可能很重要(只能由它作为0连起两个联通块),但并没有被选。

于是先按1做并查集,选出这些边,再按0,1做并查集。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 20050
#define maxe 100500
using namespace std;
int n,m,k,x,y,z,cnt0=0,cnt1=0,fath[maxv];
struct edge
{
    int u,v;
}e0[maxe],e1[maxe];
bool vis[maxe],vis0[maxe],vis1[maxe];
void reset()
{
    for (int i=1;i<=n;i++)
        fath[i]=i;
}
int getfather(int x)
{
    if (x!=fath[x])
        fath[x]=getfather(fath[x]);
    return fath[x];
}
void focus()
{
    reset();
    for (int i=1;i<=cnt1;i++)
    {
        int u=e1[i].u,v=e1[i].v;
        int f1=getfather(u),f2=getfather(v);
        if (f1!=f2) fath[f1]=f2;
    }
    for (int i=1;i<=cnt0;i++)
    {
        int u=e0[i].u,v=e0[i].v;
        int f1=getfather(u),f2=getfather(v);
        if (f1!=f2) vis[i]=true;
    }
}
bool kruskal()
{
    reset();
    int ret=0;
    for (int i=1;i<=cnt0;i++)
    {
        if (vis[i])
        {
            int u=e0[i].u,v=e0[i].v;
            int f1=getfather(u),f2=getfather(v);
            if ((f1!=f2) && (ret<k))
            {
                ret++;vis0[i]=true;
                fath[f1]=f2;
            }
        }
    }
    for (int i=1;i<=cnt0;i++)
    {
        if (!vis[i])
        {
            int u=e0[i].u,v=e0[i].v;
            int f1=getfather(u),f2=getfather(v);
            if ((f1!=f2) && (ret<k))
            {
                ret++;vis0[i]=true;
                fath[f1]=f2;
            }
        }
    }
    if (ret!=k) return false;
    for (int i=1;i<=cnt1;i++)
    {
        int u=e1[i].u,v=e1[i].v;
        int f1=getfather(u),f2=getfather(v);
        if (f1!=f2)
        {
            fath[f1]=f2;
            ret++;vis1[i]=true;
        }
    }
    if (ret!=n-1) return false;
    return true;
}
void print_e()
{
    for (int i=1;i<=cnt0;i++)
    {
        if (vis0[i])
            printf("%d %d 0\n",e0[i].u,e0[i].v);
    }
    for (int i=1;i<=cnt1;i++)
    {
        if (vis1[i])
            printf("%d %d 1\n",e1[i].u,e1[i].v);
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        if (!z)
        {
            cnt0++;
            e0[cnt0].u=x;e0[cnt0].v=y;
        }
        else
        {
            cnt1++;
            e1[cnt1].u=x;e1[cnt1].v=y;
        }
    }
    focus();
    if (!kruskal()) printf("no solution\n");
    else print_e();
    return 0;
}

 

以上是关于BZOJ 3624 免费道路的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3624,[Apio2008]免费道路

bzoj 3624 免费道路

BZOJ 3624 免费道路

bzoj3624Apio2008—免费道路

Bzoj 3624: [Apio2008]免费道路 (贪心+生成树)

BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]