题目链接:http://acm.fzu.edu.cn/problem.php?pid=2087
题意:给出一个有n个点m条边的图,没有重边和自环,问有多少条边可以是最少生成树上的边
思路:对Kruscal不熟悉……没有想出来,图上只有2种边,一种是最少生成树上的边,一种不是最少生成树上的边,每次贪心的时候有权值相同且不在同一个集合的边res++,之后将这些边全放进生成树的集合里,最终得到的答案就是所求
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define maxn 100030 using namespace std; struct edge { int x,y,w; edge(int x=0,int y=0,int w=0):x(x),y(y),w(w){} }e[maxn]; int fa[maxn]; int n,m; bool cmp(edge p,edge q) { return p.w<q.w; } int finds(int x) { if (x==fa[x]) return x; else return fa[x]=finds(fa[x]); } int Kruscal() { sort(e+1,e+m+1,cmp); int cnt=n; int res=0; for (int i=0;i<=n;i++) fa[i]=i; for (int i=1;i<=m;i++) { int pos=i; while (e[i].w==e[pos].w) { int t1=finds(e[pos].x); int t2=finds(e[pos].y); if (t1!=t2) res++; pos++; } pos=i; while (e[i].w==e[pos].w) { int t1=finds(e[pos].x); int t2=finds(e[pos].y); if (t1!=t2) fa[t1]=t2; pos++; } } return res; } int main() { int t; scanf("%d",&t); while (t--) { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w); } int res=Kruscal(); printf("%d\n",res); } }