JZOJ.5275【NOIP2017模拟8.14】水管
这个第一问很显然就是最小生成树了,跑一下kruskal或者prim就可以了。
至于第二问问是不是唯一的最小生成树,我们在跑kruskal的时候,我们可以把已经联通的点缩成一个点,然后发现一条连接某两个点的边,便再寻找是否还有其他边权值一样的边也连接着这两个点,如果有就说明最小生成树并不是唯一的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #define N 100002 8 using namespace std; 9 struct data{ 10 int a,b,c; 11 }line[N*2]; 12 int n,t,f[N],tmp,x,y,m; 13 long long ans; 14 bool qwq; 15 int find(int x){ 16 if (f[x]==x) return x; 17 f[x]=find(f[x]); 18 return f[x]; 19 } 20 bool comp(const struct data a,const struct data b){ 21 return a.c<b.c; 22 } 23 int main(){ 24 scanf("%d",&t); 25 while (t--){ 26 qwq=false; 27 scanf("%d%d",&n,&m); 28 for (int i=1;i<=m;i++){ 29 scanf("%d%d%d",&line[i].a,&line[i].b,&line[i].c); 30 if (i<=n) f[i]=i; 31 } 32 sort(line+1,line+1+m,comp); 33 tmp=0; 34 ans=0; 35 for (int i=1;i<=m;i++){ 36 if (tmp==n-1) break; 37 x=find(line[i].a); 38 y=find(line[i].b); 39 if (x!=y){ 40 if (!qwq) 41 for (int j=i+1,qoq,qvq;j<=m&&line[j].c==line[i].c;j++){ 42 qoq=find(line[j].a); 43 qvq=find(line[j].b); 44 if (((qoq==x)&&(qvq==y))||((qoq==y)&&(qvq==x))){ 45 qwq=true; 46 break; 47 } 48 } 49 f[x]=y; 50 tmp++; 51 ans+=line[i].c; 52 } 53 } 54 printf("%lld\n",ans); 55 if (qwq) printf("No\n"); 56 else printf("Yes\n"); 57 } 58 return 0; 59 }
(其实这个很容易就被卡的似乎只是数据太水了233)