zoukankan      html  css  js  c++  java
  • 图论板子 次小生成树

    由最小生成树T进行一次可行交换得到的新的生成树的集合 称为T的邻集 N(T)
    (即 最小生成树的某两节点间有重边 可替换 或 原图中存在其它边可重新连接这些节点)
    找到可替换边中权值最小的那条 替换即可
    实现:存最小生成树上每两点间最大距离,
    遍历每条不在最小生成树上的边,更新 以这条边 替换 该边两端节点间的最大距离 后的最小值

    在kruskal算法基础上实现

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<string>
    using namespace std;
    const int INF=0x3f3f3f3f;
    typedef pair<int, int> pr;
    typedef long long ll;
    #define fi first
    #define se second
    #define me(x) memset(x, -1, sizeof(x))
    #define mem(x) memset(x, 0, sizeof(x))
    #define N 10000+5
    struct node
    {
        int u, v, w;
        bool vis;
    }e[4*N];
    
    bool cmp(node a, node b)
    {
        if(a.w==b.w && a.u==b.u) return a.v<b.v;
        if(a.w==b.w) return a.u<b.u;
        return a.w<b.w;
    }
    int n, m;
    int p[N];
    vector<int> g[1005];
    
    int fin(int x)
    {
        int r=x;
        while(r!=p[r])
            r=p[r];
        int i=x, t;
        while(p[i]!=r)
        {
            t=p[i];
            p[i]=r;
            i=t;
        }
        return r;
    }
    void kruskal()
    {
        sort(e, e+m, cmp);
        int i, j, l;
        for(i=0; i<=n; i++)
            p[i]=i, g[i].clear(), g[i].push_back(i);
        int k=0, sum=0, maxn[105][105];
    
        for(i=0; i<m; i++)
        {
            if(k==n-1) break;
            int x=fin(e[i].u), y=fin(e[i].v);
            if(x!=y)
            {
    
                k++;
                p[y]=x;
                e[i].vis=true;
                sum+=e[i].w;
                int lenx=g[x].size(), leny=g[y].size();
                for(j=0; j<lenx; j++)
                    for(l=0; l<leny; l++)
                        maxn[g[x][j]][g[y][l]]=maxn[g[y][l]][g[x][j]]=e[i].w;
                        //更新两点间最大值(kruskal保证边权递增
                int tmp[1005];
                for(j=0; j<lenx; j++)
                    tmp[j]=g[x][j];
                for(l=0; l<leny; l++)
                    g[x].push_back(g[y][l]);//加点
                for(j=0; j<lenx; j++)
                    g[y].push_back(tmp[j]);//加点
            }
        }
        int sum1=INF;
        for(i=0; i<m; i++)
            if(!e[i].vis) sum1=min(sum1, sum+e[i].w-maxn[e[i].u][e[i].v]);
            //更新替换后的最小值
        //cout<<sum<<endl<<sum1<<endl;
        if(sum<sum1) cout<<sum<<endl;
        else cout<<"Not Unique!"<<endl;
    }
    
    int main()
    {
        int i, j, k, t;
        cin>>t;
        while(t--)
        {
            cin>>n>>m;
            for(i=0; i<m; i++)
                cin>>e[i].u>>e[i].v>>e[i].w, e[i].vis=false;
            kruskal();
        }
    }

    #include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#include<set>#include<string>using namespace std;const int INF=0x3f3f3f3f;typedef pair<int, int> pr;typedef long long ll;#define fi first#define se second#define me(x) memset(x, -1, sizeof(x))#define mem(x) memset(x, 0, sizeof(x))#define N 10000+5struct node{    int u, v, w;    bool vis;}e[4*N];
    bool cmp(node a, node b){    if(a.w==b.w && a.u==b.u) return a.v<b.v;    if(a.w==b.w) return a.u<b.u;    return a.w<b.w;}int n, m;int p[N];vector<int> g[1005];
    int fin(int x){    int r=x;    while(r!=p[r])        r=p[r];    int i=x, t;    while(p[i]!=r)    {        t=p[i];        p[i]=r;        i=t;    }    return r;}void kruskal(){    sort(e, e+m, cmp);    int i, j, l;    for(i=0; i<=n; i++)        p[i]=i, g[i].clear(), g[i].push_back(i);    int k=0, sum=0, maxn[105][105];
        for(i=0; i<m; i++)    {        if(k==n-1) break;        int x=fin(e[i].u), y=fin(e[i].v);        if(x!=y)        {
                k++;            p[y]=x;            e[i].vis=true;            sum+=e[i].w;            int lenx=g[x].size(), leny=g[y].size();            for(j=0; j<lenx; j++)                for(l=0; l<leny; l++)                    maxn[g[x][j]][g[y][l]]=maxn[g[y][l]][g[x][j]]=e[i].w;                    //更新两点间最大值(kruskal保证边权递增            int tmp[1005];            for(j=0; j<lenx; j++)                tmp[j]=g[x][j];            for(l=0; l<leny; l++)                g[x].push_back(g[y][l]);//加点            for(j=0; j<lenx; j++)                g[y].push_back(tmp[j]);//加点        }    }    int sum1=INF;    for(i=0; i<m; i++)        if(!e[i].vis) sum1=min(sum1, sum+e[i].w-maxn[e[i].u][e[i].v]);        //更新替换后的最小值    //cout<<sum<<endl<<sum1<<endl;    if(sum<sum1) cout<<sum<<endl;    else cout<<"Not Unique!"<<endl;}
    int main(){    int i, j, k, t;    cin>>t;    while(t--)    {        cin>>n>>m;        for(i=0; i<m; i++)            cin>>e[i].u>>e[i].v>>e[i].w, e[i].vis=false;        kruskal();    }}

  • 相关阅读:
    机器学习框架之sklearn简介
    ubuntu 16.04下使用 python pip的安装问题。
    ubuntu 16.04 搭建git小型服务器
    使用config 来管理ssh的会话
    【linux】su、sudo、sudo su、sudo -i的用法和区别
    【python】确保文件写入结束
    【python】描述符descriptor
    【python】类(资料+疑惑)
    【pymongo】mongodb cursor id not valid error
    【python】继承关系和isinstance
  • 原文地址:https://www.cnblogs.com/op-z/p/11281912.html
Copyright © 2011-2022 走看看