http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2494
题意:
给你一个图,该图可能存在很多最小生成树。求最小生成树可能包含的边的个数。
思路:
这里我们将权值相同的边看成一个块,按块来处理。按krusal的算法处理,检查每一块当该边加入后最小生成树后不会形成环就+1,这里我们先不把他们加入,检查完后再将边加入,这样就能保证可能加入最小生成树的相同的权值的边都加入了,并且我们也计数了。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll long long #define inf 0x7f7f7f7f #define MOD 1073741824 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 500007 #define N 100007 using namespace std; //freopen("din.txt","r",stdin); struct node { int u,v,w; }g[M]; int f[N]; int n,m; int cmp(node a,node b) { return a.w < b.w; } int find(int x) { if (x != f[x]) f[x] = find(f[x]); return f[x]; } void Kruscal() { int i,j; int ans = 0; for (i = 1; i <= n; ++i) f[i] = i; sort(g,g + m,cmp); for (i = 0; i < m; i = j) { for (j = i; j < m; ++j) { if (g[j].w != g[i].w) break; if (find(g[j].u) != find(g[j].v)) ans++; } for (int k = i; k < j; ++k) { f[find(g[k].u)] = find(g[k].v); } } printf("%d\n",ans); } int main() { //freopen("din.txt","r",stdin); int i,j; while (~scanf("%d%d",&n,&m)) { for (i = 0; i < m; ++i) { scanf("%d%d%d",&g[i].u,&g[i].v,&g[i].w); } Kruscal(); } }
来源:https://www.cnblogs.com/E-star/archive/2012/12/03/2800112.html