次小生成树【模板】

给一个图,判断图的最小生成树是否唯一。

End[]记录邻接表尾节点的位置。MST表示最小生成树的大小,SecMST表示次小生成树的大小。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 1010;
const int MAXM = 100010;

int father[MAXN];

int find(int x)
{
    if(x != father[x])
        father[x] = find(father[x]);
    return father[x];
}

struct Node
{
    int from;
    int to;
    int w;
    bool vis;
};
Node Edges[MAXM];//存储边信息

bool cmp(Node a, Node b)
{
    return a.w < b.w;
}

//链式前向星
struct Node1
{
    int to;
    int next;
};
Node1 Vertex[MAXN];//边数组,表示结点连向的边

int N,M;
int head[MAXN];     //邻接表头结点位置
int End[MAXN];      //邻接表尾结点位置,方便合并
int Len[MAXN][MAXN];//图中两点之间在最小生成树上路径最长的边

void Kruskal()
{
    int x,y,k = 0;
    int ans = 0;

    //初始化邻接表,每个节点初始的时候添加一条指向自己的边,表示结点i各自为一个集合
    memset(head,-1,sizeof(head));
    memset(End,-1,sizeof(End));
    for(int i = 1; i <= N; i++)
    {
        Vertex[i].to = i;
        Vertex[i].next = head[i];
        End[i] = i;
        head[i] = i;
    }

    sort(Edges,Edges+M,cmp);//边按权值排序
    for(int i = 0; i < M; i++)
    {
        if(k == N-1)
            break;
        if(Edges[i].w < 0)
            continue;
        x = find(Edges[i].from);
        y = find(Edges[i].to);
        if(x != y)
        {
            //遍历两个节点所在的集合
            for(int w = head[x]; w != -1; w = Vertex[w].next)
            {
                for(int v = head[y]; v != -1; v = Vertex[v].next)
                {
                    Len[Vertex[w].to][Vertex[v].to] = Len[Vertex[v].to][Vertex[w].to] = Edges[i].w;
                    //当前加入的边一定是加(x,y)边成环后删去的除(x,y)外长度最大的边
                }
            }
            Vertex[End[y]].next = head[x];//合并两个邻接表,表示两点已连边连在一个集合中,最终连成一个最小生成树
            head[x] = head[y];
            End[y] = End[x];
            father[y] = x;
            k++;
            Edges[i].vis = true;
        }
    }
}

int main()
{
    int T,x,y,w;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        for(int i = 1; i <= N; i++)
            father[i] = i;
        memset(Len,0x7f,sizeof(Len));
        for(int i = 0; i < M; i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            Edges[i].from = x;
            Edges[i].to = y;
            Edges[i].w = w;
            Edges[i].vis = false;
        }

        int MST,SecMST;
        Kruskal();
        MST = 0;//最小生成树长度
        for(int i = 0; i < M; i++)
        {
            if(Edges[i].vis)
                MST += Edges[i].w;
        }
        SecMST = 0xfffff0;
        for(int i = 0; i < M; i++)
        {
            if(!Edges[i].vis)//加边,并删去最小生成树上的边
                SecMST = min(SecMST,MST+Edges[i].w - Len[Edges[i].from][Edges[i].to]);
        }
        if(SecMST == MST)
            printf("Not Unique!\n");
        else
            printf("%d\n",MST);
    }

    return 0;
}
时间: 2024-10-27 16:57:18

次小生成树【模板】的相关文章

poj 2831 次小生成树模板

/*次小生成树 题意:给你一些路径,现在将一部分路径权值减少后问是否可以替代最小生成树里面的边. 解:次小生成树,即将这条边连上,构成一个环 求出任意两点路径之间的除了这条边的最大值,比较这个最大值>=这条边,说明可以替换. prime算法次小生成树模板 */ #include<stdio.h> #include<string.h> #define N 1100 #define inf 0x3fffffff int ma[N][N]; int Min(int a,int b)

POJ_1679_The Unique MST(次小生成树模板)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 23942   Accepted: 8492 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

次小生成树模板

1 kruskal 2 #include <vector> 3 #include <iostream> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #define INF 0x3f3f3f3f 8 9 using namespace std; 10 int n,m; 11 struct data 12 { 13 int u,v,w; 14 bool vis;

uva10600次小生成树模板题

裸题,上模板就行,注意j  !  =  k #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cassert> #include<iomanip> #include<cstdlib> #include&

洛谷 P4180 【模板】严格次小生成树[BJWC2010]【次小生成树】

严格次小生成树模板 算法流程: 先用克鲁斯卡尔求最小生成树,然后给这个最小生成树树剖一下,维护边权转点权,维护最大值和严格次大值. 然后枚举没有被选入最小生成树的边,在最小生成树上查一下这条边的两端点的路径上的最长边,如果最长边等于枚举到的边的边权,那么选次长边(没有次长边的话直接跳过),然后在最小生成树的权值上减去路径上最/次长边,加上当前枚举的边的边权 因为如果加入枚举的边的,那么就形成了一个环,需要断开一条边 注意一开始单点次小值赋为0 #include<iostream> #inclu

POJ 1679 prime次小生成树判定生成树是否唯一

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21931   Accepted: 7784 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

[BJOI 2010]次小生成树Tree

Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值)  这下小 C 蒙了,他找到了你,希望你帮他解决这个问题. Input 第一行包含两个整数N 和M,表示无向图

图论——次小生成树

次小生成树模板 通过poj 1679 #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <stack> #include <queue> #include <set> using namespace std; #define INF 10000000

一本通1555【例 4】次小生成树

1555:[例 4]次小生成树 时间限制: 1000 ms         内存限制: 524288 KB 题目描述 原题来自:BeiJing 2010 组队赛 给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树. 设最小生成树的边权之和为 sum,严格次小生成树就是指边权之和大于 sum 的生成树中最小的一个. 输入格式 第一行包含两个整数 N 和 M,表示无向图的点数与边数: 接下来 MM 行,每行三个数 x,y,z,表示点 x 和点 y 之间有一条边,边的权值为 z. 输出格式

Luogu P4180 【模板】严格次小生成树[BJWC2010]

P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得意之时,小\(P\)又来泼小\(C\)冷水了.小\(P\)说,让小\(C\)求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是\(E_M\),严格次小生成树选择的边集是\(E_S\),那么需要满足:(\(value(e)\)表示边\(e\)的权值)\