您的位置:首页 > 其它

FZU 2087 统计树边

2016-04-14 11:33 225 查看
题目链接: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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: