FZU 2087 统计树边

这题第一直觉就是和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\n",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;
}

 

posted @ 2016-03-04 16:48  Fighting_Heart  阅读(212)  评论(0编辑  收藏  举报