UVA 1151 Buy or build(并查集之六)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA 1151 Buy or build(并查集之六)相关的知识,希望对你有一定的参考价值。

题意:n个结点,以及m个组合,可以任意选择。求最小花费。

因为组合最多只有8个,可以枚举。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<string.h>
#define MAX 1007
#define INTMAX (int)1e9
using namespace std;
struct list_buy
{
    int num;
    int price;
    int node[MAX];
};
struct list_buy l[10];
struct point
{
    int x;
    int y;
};
struct point p[MAX];
struct Line
{
    int u;
    int v;
    int w;
};
struct Line line[MAX*MAX];
int n,m,x[10],flag[MAX],count_line,min_ans;
int pre[MAX];
int cmp(struct Line a,struct Line b)
{
    return a.w<b.w;
}
int cal(struct point a,struct point b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
void init()
{
    for(int i=0;i<n;i++)
    {
        pre[i]=i;
        flag[i]=0;
    }
}
int find(int x)
{
    int r=x;
    while(r!=pre[r])
        r=pre[r];
    int i=x,j;
    while(i!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;
}
void join(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
        pre[fx]=fy;
}
int kruskal()
{
    int ans=0;
    sort(line,line+count_line,cmp);
    for(int i=0;i<count_line;i++)
    {
        int fx=find(line[i].u);
        int fy=find(line[i].v);
        if(fx!=fy)
        {
            ans+=line[i].w;
            pre[fx]=fy;
            for(int j=0;j<n;j++)
                pre[j]=find(j);
            int temp=0;
            for(int j=0;j<n-1;j++)
            {
                if(pre[j]!=pre[j+1])
                {
                    temp=1;
                    break;
                }
            }
            if(temp==0)
                return ans;
        }
    }
    return ans;
}
int solve()
{
    int ans=0;
    init();
    for(int i=0;i<m;i++)
    {
        if(x[i])
        {
            ans+=l[i].price;
            for(int j=0;j<l[i].num-1;j++)
            {
                int fx=find(l[i].node[j]);
                int fy=find(l[i].node[j+1]);
                pre[fx]=fy;
            }
        }
    }
    int temp=0;
    for(int i=0;i<n-1;i++)
    {
        if(pre[i]!=pre[i+1])
        {
            temp=1;
            break;
        }
    }
    if(temp==0)
        return ans;
    else
    {
        temp=kruskal();
        if(temp!=-1)
            ans+=temp;
        else
            return -1;
    }
    return ans;
}
void fun(int t)
{
    if(t>=m)
    {
        int ans=solve();
        if(ans<min_ans&&ans!=-1)
            min_ans=ans;
    }
    else
    {
        for(int i=0;i<=1;i++)
        {
            x[t]=i;
            fun(t+1);
        }
    }
}
int main()
{
    int T;
    //freopen("in.cpp","r",stdin);
    while(scanf("%d",&T)!=EOF)
    {
        while(T--)
        {
            count_line=0;
            min_ans=INTMAX;
            scanf("%d%d",&n,&m);
            for(int i=0;i<m;i++)
            {
                scanf("%d%d",&l[i].num,&l[i].price);
                for(int j=0;j<l[i].num;j++)
                {
                    scanf("%d",&l[i].node[j]);
                    l[i].node[j]--;
                }
            }
            for(int i=0;i<n;i++)
            {
                scanf("%d%d",&p[i].x,&p[i].y);
            }
            for(int i=0;i<n;i++)
            {
                for(int j=i+1;j<n;j++)
                {
                    if(i==j)
                        continue;
                    line[count_line].u=i;
                    line[count_line].v=j;
                    line[count_line].w=cal(p[i],p[j]);
                    count_line++;
                }
            }
            fun(0);
            printf("%d\n",min_ans);
            if(T!=0) printf("\n");
        }
    }
    return 0;
}

 

以上是关于UVA 1151 Buy or build(并查集之六)的主要内容,如果未能解决你的问题,请参考以下文章

[UVA - 1151] Buy or Build 题解

UVa 1151 - Buy or Build(最小生成树)

UVa1151 Buy or Build (最小生成树,枚举子集)

uva 1151Buy or Build(图论 最小生成树)

UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)

UVA 1151 Buy or Build (有某些特别的东东的最小生成树)