当前位置: 代码迷 >> 综合 >> FZU 2087 统计树边
  详细解决方案

FZU 2087 统计树边

热度:46   发布时间:2024-01-20 20:24:20.0

[题目大意]

给定一个无向图,求出这些边(至少出现在一棵生成树中的边)的数目。

[解题思路]

理解MST的思想,将贪心思想运用。

由小到大遍历这些边,权值相同的为一组。

先判断这些边是否能够成为树边,再对这些边进行合并。

[注意事项]

不知道为何,以前一直写的模板不顶用了...

一定要改成比较丑的样子...

[Code]

#include<iostream>
#include<cstdio>
#include<algorithm>
#define FF(i,N) for( int i=0;i<N;i++ )
using namespace std;struct edge{int u,v,len;
}E[111111];
int n,m;
int fat[111111];int getf( int x ){if( fat[x]==x ) return x;else return fat[x]=getf(fat[x]);
}bool cmp( edge a,edge b ){ return a.len<b.len; }
int krus()
{sort( E,E+m,cmp );memset( fat,0,sizeof(fat) );for( int i=0;i<=n;i++ ) fat[i]=i;int ret=0,pre=-1;for( int i=0;i<=m;i++ ){if( pre!=-1&&E[pre].len!=E[i].len ){for( int j=pre;j<i;j++ )if( getf(E[j].u)!=getf(E[j].v) )ret++;for( int j=pre;j<i;j++ )fat[getf(E[j].u)]=getf(E[j].v);//fat[fat[(E[j].u]]=fat[E[j].v];pre=-1;}if( pre==-1 )pre=i;}return ret;
}int main()
{int t;scanf("%d",&t);while( t-- ){scanf( "%d %d",&n,&m );E[m].len=INT_MAX;FF(i,m) scanf( "%d%d%d",&E[i].u,&E[i].v,&E[i].len );printf( "%d\n",krus() );}return 0;
}