简单最小生成树。
就是读题很纠结,什么原有的路,新建的路,删除的村庄。
总之,所有给的边都加上,删除点的操作就是把与该点相连的所有边删除(边权变成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;
}