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();
}
}