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