这题第一直觉就是和CF第三次教育场的E题是一样的,
http://codeforces.com/contest/609/problem/E
然后直接拉过来代码改了改,提交返回MLE。FZU内存开的小,没救了。
后来还是同学指教,边总共只有两类,要么存在最少生成树上,要么不属于任何一个最小生成树。
所以只要按边权从小到大往图中加边,对于相同权值的边,如果两端不在一个集合中,那么答案+1,
然后再对相同权值的边加入到图中。
#include <cstdio> #include <vector> #include <map> #include <algorithm> using namespace std; const int maxn=100000+10; int fa[maxn]; struct Edge { int a,b,v; }e[maxn]; vector<Edge>v[1000]; int n,m; int Find(int x) { if(x!=fa[x]) fa[x]=Find(fa[x]); return fa[x]; } void read() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].v); for(int i=0;i<=500;i++) v[i].clear(); for(int i=0;i<m;i++) v[e[i].v].push_back(e[i]); } void work() { int ans=0; for(int i=1;i<=500;i++) { if(v[i].size()==0) continue; for(int j=0;j<v[i].size();j++) { int fu=Find(v[i][j].a); int fv=Find(v[i][j].b); if(fu!=fv) ans++; } for(int j=0;j<v[i].size();j++) { int fu=Find(v[i][j].a); int fv=Find(v[i][j].b); if(fu!=fv) fa[fu]=fv; } } printf("%d ",ans); } void init() { for(int i=1;i<=n;i++) fa[i]=i; } int main() { int T; scanf("%d",&T); while(T--) { read(); init(); work(); } return 0; }