zoukankan      html  css  js  c++  java
  • 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
    ",e0[i].u,e0[i].v);
        }
        for (int i=1;i<=cnt1;i++)
        {
            if (vis1[i])
                printf("%d %d 1
    ",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
    ");
        else print_e();
        return 0;
    }
  • 相关阅读:
    面向对象的程序设计-继承
    Chrome开发工具之Console
    面向对象的程序设计-原型模式
    面向对象的程序设计-工厂模式、构造函数模式
    面向对象的程序设计-理解对象
    引用类型-Array类型
    引用类型-Object类型
    单体内置对象
    基本包装类型
    引用类型-Function类型
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5840528.html
Copyright © 2011-2022 走看看