hdu3080 The plan of city rebuild

时间:2022-05-05 00:47:53

简单最小生成树。

就是读题很纠结,什么原有的路,新建的路,删除的村庄。

总之,所有给的边都加上,删除点的操作就是把与该点相连的所有边删除(边权变成inf就是了),然后求最小生成树。

kruskal比较方便判断不连通的情况。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;

struct node
{
    int u,v,w;
}e[40000];

int vis[210],r[210],n,tmp,edge;

int root(int a)
{
    if(a!=r[a])
        r[a]=root(r[a]);
    return r[a];
}

bool cmp(node a,node b)
{
    if(a.w!=b.w) return a.w<b.w;
    if(a.u!=b.u) return a.u<b.u;
    return a.v<b.v;
}

int kru()
{
    int k=0,i,ans=0,flag=0;
    sort(e,e+edge,cmp);
    for(i=0;i<edge;i++)
    {
        if(k==tmp-1)
        {
            flag=1;
            break;
        }
        if(e[i].w==inf) break;
        int ra=root(e[i].u);
        int rb=root(e[i].v);
        if(ra!=rb)
        {
            r[ra]=rb;
            k++;
            ans+=e[i].w;
        }
    }
    if(flag) return ans;
    else return -1;
}

int main()
{
    int t,i,j,l1,l2,e1,e2,m,a,ans;
    scanf("%d",&t);
    while(t--)
    {
        edge=0;
        scanf("%d%d",&l1,&e1);
        for(i=0;i<e1;i++)
        {
            scanf("%d%d%d",&e[edge].u,&e[edge].v,&e[edge].w);
            edge++;
        }
        scanf("%d%d",&l2,&e2);
        for(i=0;i<e2;i++)
        {
            scanf("%d%d%d",&e[edge].u,&e[edge].v,&e[edge].w);
            edge++;
        }
        n=l1+l2;
        tmp=n;
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d",&a);
            for(j=0;j<edge;j++)
                if(e[j].u==a||e[j].v==a)
                    e[j].w=inf;
            vis[a]=1;
            tmp--;
        }
        if(tmp<=1)
        {
            printf("0\n");
            continue;
        }
        for(i=0;i<=n;i++)
            r[i]=i;
        ans=kru();
        if(ans==-1) printf("what a pity!\n");
        else printf("%d\n",ans);
    }
    return 0;
}