题解:
我从未见过如此厚颜无耻之题。。。卡内存卡时间,还是道水题,典型的最小生成树的题,用克鲁斯卡尔算法,先并查集连好点,然后日常操作,我比赛的时候怎么交都是爆内存。。比完赛才发现把优先队列改成数组拍一下序就不会爆内存了。。。神坑,而且过的时候还是998ms。。。差2ms就没过,为什么有这种坑题,后来问学长是因为优先队列比较耗内存。。。先让我哭一会
代码:
#include<iostream> #include<stdio.h> #include<string> #include<cstring> #include<map> #include<queue> #include<stack> #include<algorithm> #include<math.h> #include<deque> #include<stack> using namespace std; int m,n,k,tot; struct edge { int f,t; int v; }; int cmp(const edge& x,const edge& y) { return x.v<y.v; } edge a[25005]; int pre[505];//保存根节点 int find(int x)//寻找更节点,压缩路径 { if(x!=pre[x]) pre[x]=find(pre[x]); return pre[x]; } void init() { int i,j; for(i=1;i<=n;i++) { pre[i]=i;//初始化根节点 } } int main() { int i,j,test,d1,z,d2,s; edge t; scanf("%d",&test); while(test--) { s=0; scanf("%d%d%d",&n,&m,&k); init(); tot=0; for(i=0;i<m;i++) { scanf("%d%d%d",&t.f,&t.t,&t.v); a[i]=t; } for(i=0;i<k;i++) { int x,y; scanf("%d",&x); scanf("%d",&y);//吓得我不敢开内存 d1=find(y); for(j=1;j<x;j++) { scanf("%d",&z); d2=find(z); if(d1!=d2) { pre[d2]=d1; tot++; } } } sort(a,a+m,cmp);//为了贪心排序 for(i=0;i<m;i++) { t=a[i]; d1=find(t.f); d2=find(t.t); if(d1!=d2)//并查集操作 { s+=t.v; tot++;//边数加一 pre[d2]=d1; } if(tot>=n-1)//生成树建好 break; } if(tot>=n-1) printf("%d\n",s); else printf("-1\n"); } return 0; }