POJ1679 The Unique MST 生成树+DFS

Posted WDZRMPCBIT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1679 The Unique MST 生成树+DFS相关的知识,希望对你有一定的参考价值。

题意:求一个无向图的最小生成树与次小生成树的边权和是否相等

题解:

首先有一个性质,就是最小生成树上的任意两点的距离就是其在原图中的最短路,严格的证明我不会- -,但是由于Prim Dijkstra算法的过程完全相同,所以这个性质比较显然(不会证就不会证呗为何还要找理由QAQ)

还要一条性质就是无向MST上加入一条边一定会形成一个环,因此我们可以枚举加入一条不在MST上的边e,然后删除MST上形成的环中除e之外的最长的一条边,得到了一个新的最小生成树,由于e一定大于等于删除的那条边,因此得到的新的生成树也一定大于等于MST,因此枚举出的最小的生成树就是次小生成树了。

当然实际操作的时候并不需要每次都找一边最长的边,我们先把MST给存下来,然后DFS出MST上任意两点(i,j)路径上的最长边f[i][j],然后枚举的过程中的新的生成树的长度就是dist_MST+w(u,v)-f[u][v]

#include <queue>
#include <vector>
#include <functional>
#include <cstdio>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=100+2;
const int MAXM=10000+2;
struct HASH{
    int u,w;
    HASH *next;
    HASH(){}
    HASH(int _u,int _w,HASH *_next):u(_u),w(_w),next(_next){}
}*table[MAXN],mem[2*MAXM],*table_MST[MAXN],mem_MST[2*MAXM];
struct NODE{
    int u,v,w;
    NODE(){}
    NODE(int _u,int _v,int _w):u(_u),v(_v),w(_w){}
    friend bool operator<(NODE a,NODE b){ return a.w>b.w;}
};
int T,N,M,dist,d[MAXN],e[MAXN][MAXN],cnt;
bool flag[MAXN],mark[MAXN][MAXN];
priority_queue<NODE> q;

void Insert(int u,int v,int w){ table[u]=&(mem[cnt++]=HASH(v,w,table[u]));}

void Insert_MST(int u,int v,int w){ table_MST[u]=&(mem_MST[cnt++]=HASH(v,w,table_MST[u]));}

int Prim(){
    int ret=0;
    memset(d,0X7F,sizeof(d));
    d[1]=0,q.push(NODE(0,1,0));

    NODE x;
    while(!q.empty()){
        x=q.top(),q.pop();
        if(flag[x.v]) continue;
        flag[x.v]=1;

        ret+=x.w;
        if(x.u) mark[x.u][x.v]=mark[x.v][x.u]=1,Insert_MST(x.u,x.v,x.w),Insert_MST(x.v,x.u,x.w);

        for(HASH *p=table[x.v];p;p=p->next)
            if(d[p->u]>p->w) d[p->u]=p->w,q.push(NODE(x.v,p->u,p->w));
    }

    return ret;
}

void DFS(int u,int w,int f,int b){
    for(HASH *p=table_MST[u];p;p=p->next)
        if(p->u!=f) e[b][p->u]=max(w,p->w),DFS(p->u,max(w,p->w),u,b);
}

int main(){
    cin >> T;
    while(T--){
        cnt=dist=0;
        memset(e,0,sizeof(e));
        memset(mark,0,sizeof(mark));
        memset(flag,0,sizeof(flag));
        memset(table,0,sizeof(table));
        memset(table_MST,0,sizeof(table_MST));

        cin >> N >> M;
        for(int i=1,u,v,w;i<=M;i++){
            cin >> u >> v >> w;
            Insert(u,v,w),Insert(v,u,w);
        }

        cnt=0,dist=Prim();
        for(int i=1;i<=N;i++) DFS(i,0,0,i);

        for(int i=1;i<=N;i++)
            for(HASH *p=table[i];p;p=p->next)
                if(!mark[i][p->u] && p->w==e[i][p->u]){
                    flag[0]=1;
                    break;
                }
        if(flag[0]) cout << "Not Unique!" << endl;
        else cout << dist << endl;
    }

    return 0;
}
View Code

 

以上是关于POJ1679 The Unique MST 生成树+DFS的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1679 The Unique MST (次小生成树)

POJ 1679 The Unique MST(次短生成树)

poj 1679 The Unique MST (判定最小生成树是否唯一)

POJ 1679 The Unique MST 最小生成树/次小生成树

POJ 1679 The Unique MST 推断最小生成树是否唯一

POJ 1679 The Unique MST(次小生成树)