FZU 2087 统计树边【MST相关】

 Problem 2087 统计树边

Accept: 212    Submit: 651

Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

在图论中。树:随意两个顶点间有且仅仅有一条路径的图。

生成树:包括了图中全部顶点的一种树。

最小生成树:对于连通的带权图(连通网)G,其生成树也是带权的。

生成树T各边的权值总和称为该树的权,权最小的生成树称为G的最小生成树(Minimum Spanning Tree)。最小生成树可简记为MST。

可是。对于一个图而言。最小生成树并非唯一的。

如今,给你一个连通的有权无向图,图中不包括有自环和重边,你的任务就是寻找出有多少条边,它至少在一个最小生成树里。图保证连通。

 Input

输入数据第一行包括一个整数T,表示測试数据的组数。对于每组測试数据:

第一行包括两个整数n,m(1<n<100000,n-1<m<100000)。接下来m行。每行三个整数a,b,v(1<=a,b<=n,1<v<500),表示第i条路线连接景点A和景点B,距离是V。

两个数字之间用空格隔开。

 Output

对于每组測试数据。输出一行。包括一个整数,表示满足条件的边的个数。

 Sample Input

1

4 5

1 2 101

1 3 100

2 3 2

2 4 2

3 4 1

 Sample Output

4

 Source

福州大学第九届程序设计竞赛

思路:用kruskal算法模拟生成树的过程。

同一时候也是一个贪心生成树的过程,我们知道。生成的树的边权值和是一定的。那么对于边的替换的值也是可以确定的:仅仅有权值同样的边才有可能是还有一种生成树方法的边。

然后我就呆萌的记录有多少重边权值的边,然后加上n-1,开开心心的提交,实力WA。

一组数据就能够干掉我:

3 3

1 2 1

1 2 2

2 3 1

所以记得一定不要跟我犯一样的错误,我们须要的是动态推断一条边权值同样的边是否能可能是还有一种生成树方法的边。

我们直接在kruskal算法过程中加上动态推断的成分就能够了。那么要怎样推断呢?遍历每一条边的时候,假设有同样权值的边。像kruskal一样的推断条件,推断这条边是否能增加生成树中就可以。

kruskal算法推断一条边是否可以贪心的增加生成树中:

        for(int i=0;i<m;i++)
        {
            if(find(a[i].x)!=find(a[i].y))
            {
                zhongquanzhi+=a[i].w;
                merge(a[i].x,a[i].y);
            }
        }

我们对同权值的边推断是否能增加生成树中,而且别忘记对边要进行入树:

        for(int i=0;i<m;i=j)
        {
            for(j=i;a[i].w==a[j].w;j++)
            {
                if(find(a[j].x)!=find(a[j].y))
                {
                    output++;
                }
            }
            for(j=i;a[i].w==a[j].w;j++)
            {
                if(find(a[j].x)!=find(a[j].y))
                {
                    merge(a[j].x,a[j].y);
                }
            }
        }

完整的AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int f[1000050];
struct path
{
    int x,y,w;
}a[100050];
int cmp(path a,path b)
{
    return a.w<b.w;
}
int find(int x)
{
    return f[x] == x ? x : (f[x] = find(f[x]));
}
void merge(int a,int b)
{
    int A,B;
    A=find(a);
    B=find(b);
    if(A!=B)
    f[B]=A;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            f[i]=i;
        }
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
        }
        sort(a,a+m,cmp);
        int output=0;
        int j;
        for(int i=0;i<m;i=j)
        {
            for(j=i;a[i].w==a[j].w;j++)
            {
                if(find(a[j].x)!=find(a[j].y))
                {
                    output++;
                }
            }
            for(j=i;a[i].w==a[j].w;j++)
            {
                if(find(a[j].x)!=find(a[j].y))
                {
                    merge(a[j].x,a[j].y);
                }
            }
        }
        printf("%d\n",output);
    }
}

时间: 2024-10-10 13:58:53

FZU 2087 统计树边【MST相关】的相关文章

[ACM] FZU 2087 统计数边 (有多少边至少存在一个最小生成树里面)

Problem Description 在图论中,树:任意两个顶点间有且只有一条路径的图. 生成树:包含了图中所有顶点的一种树. 最小生成树:对于连通的带权图(连通网)G,其生成树也是带权的.生成树T各边的权值总和称为该树的权,权最小的生成树称为G的最小生成树(Minimum Spanning Tree).最小生成树可简记为MST. 但是,对于一个图而言,最小生成树并不是唯一的. 现在,给你一个连通的有权无向图,图中不包含有自环和重边,你的任务就是寻找出有多少条边,它至少在一个最小生成树里.图保

FZU-2087 统计树边(最小生成树)

Problem 2087 统计树边 Accept: 223    Submit: 693Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description 在图论中,树:任意两个顶点间有且只有一条路径的图. 生成树:包含了图中所有顶点的一种树. 最小生成树:对于连通的带权图(连通网)G,其生成树也是带权的.生成树T各边的权值总和称为该树的权,权最小的生成树称为G的最小生成树(Minimum Spanning Tree).最小生

顺序统计树

/* * 顺序统计树 */ public class OrderStatisticTree { public static final OsTreeNode NIL = new OsTreeNode(RbColor.BLACK,0); private OsTreeNode root = null; public static void main(String[] args) { OrderStatisticTree ost = new OrderStatisticTree(); //测试插入 o

zjoi 2008 树的统计——树链剖分

比较基础的一道树链剖分的题 大概还是得说说思路 树链剖分是将树剖成很多条链,比较常见的剖法是按儿子的size来剖分,剖分完后对于这课树的询问用线段树维护--比如求路径和的话--随着他们各自的链向上走,直至他们在同一条链上为止.比较像lca的方法,只不过这里是按链为单位,而且隔壁的SymenYang说可以用树链剖分做lca..吓哭 然后说说惨痛的调题经历:边表一定要开够啊! 不是n-1 而是2*(n-1)啊! 然后写变量时原始值和映射值要搞清楚啊! 不要搞错了! 还有就是下次求最小值一定看清下界是

fzu 2171 线段树 lazy标记

http://acm.fzu.edu.cn/problem.php?pid=2171      Problem 2171 防守阵地 II Accept: 73    Submit: 256Time Limit: 3000 mSec    Memory Limit : 32768 KB Problem Description 部队中总共有N个士兵,每个士兵有各自的能力指数Xi,在一次演练中,指挥部确定了M个需要防守的地点,指挥部将选择M个士兵依次进入指定地点进行防守任务,获得的参考指数即为M个士兵

FZU 2105 (线段树)

 Problem 2105 Digits Count  Problem Description Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations: Operation 1: AND opn L R Here opn, L and R are integers. For L≤i≤R, we do A[i]=A[i] AND opn (here "AND" is bitwise operation

最大最小值以及前驱后继操作最坏情况都为O(1)的顺序统计树

问题:通过为结点增加指针的方式,试说明如何在扩张的顺序统计树上,支持每一动态集合查询操作MINIMUM,MAXIMUM,SUCCESSOR和PREDECESSOR在最坏时间O(1)内完成.顺序统计树上的其他操作的渐近性能不应受影响. 代码如下: //本程序在原有的红黑树基础上增加了子树结点个数,前驱后继结点以及最大小结点属性. #include <iostream> #include <time.h> using namespace std; #define BLACK 0 #de

hdu 4123 Bob’s Race (树的直径相关+rmq+单调队列思想)

Bob's Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2115    Accepted Submission(s): 658 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble

fzu 2171 线段树区间更新

http://acm.fzu.edu.cn/problem.php?pid=2171  Problem 2171 防守阵地 II Accept: 105    Submit: 415Time Limit: 3000 mSec    Memory Limit : 32768 KB  Problem Description 部队中总共有N个士兵,每个士兵有各自的能力指数Xi,在一次演练中,指挥部确定了M个需要防守的地点,指挥部将选择M个士兵依次进入指定地点进行防守任务,获得的参考指数即为M个士兵的能