Yes
次小生成树,用的克鲁斯卡尔实现,先找到最小生成树,然后开始枚举,每次排除一条边, 看是否能找到下一个最小生成树,找到的时候一定要判断是不是已经把每一条边全部连入!
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> using namespace std; int father[510]; int n,m; struct Edge { int a; int b; int w; int f; }s[200010]; void init() { int i; for(i=1;i<=n;i++) { father[i] = i; } } int cmp(Edge a,Edge b)//从小到大排序 { return a.w<b.w; } int find(int x) { if(x==father[x]) { return x; } else { return father[x] = find(father[x]); } } int fun(int x) { int i; int sum = 0; for(i=0;i<m;i++) { if(i!=x) //去掉之前最小生成树的一条边, { int fa = find(s[i].a); int fb = find(s[i].b); if(fa!=fb) { father[fa] = fb; sum+=s[i].w; } } } int s = find(1);//判断全部的点是不是已经全部连进去 for(i=2;i<=n;i++) { if(father[i]!=s) { return -1; } } return sum; } int main() { int T; scanf("%d",&T); int sum; while(T--) { scanf("%d%d",&n,&m); int i,j; init(); for(i=0;i<m;i++) { scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].w); s[i].f = 0; } sort(s,s+m,cmp); sum = 0; for(i=0;i<m;i++)//先求出最小生成树 { int fa = find(s[i].a); int fb = find(s[i].b); if(fa!=fb) { father[fa] = fb; s[i].f = 1; sum += s[i].w; //找到最小生成树的值 } } int count = 0 ; bool flag = false; for(i=0;i<m;i++)//枚举所有的边 { if(s[i].f) //每次排除一条边 { init(); if(sum==fun(i)) { flag = true; break; } } if(flag) break; } if(flag) printf("Yes\n"); else printf("No\n"); } return 0; }