1. 程式人生 > >次最小生成樹 模版

次最小生成樹 模版

define ios truct rep com mem num 代碼 div

次小生成樹(轉)

轉載(http://www.cnblogs.com/z360/p/6875488.html)

所謂次小生成樹,顧名思義就是從生成樹中取出的第二小的生成樹。

我們在前面已經說過最小生成樹的概念及代碼實現了,所以接下來要說的次小生成樹應該比較簡單理解了。

求次小生成樹的兩種方法

1:首先求出最小生成樹T,然後枚舉最小生成樹上的邊,計算除了枚舉的當前最小
生成樹的邊以外的所有邊形成的最小生成樹Ti,然後求最小的Ti就是次小生成樹。
2:首先計算出最小生成樹T,然後對最小生成樹上任意不相鄰的兩個點 (i,j)
添加最小生成樹以外的存在的邊形成環,然後尋找i與j之間最小生成樹上最長的邊刪去,

計算map[i][j](最小生成樹以外存在的邊) 與 maxd[i][j](最小生成樹上最長的邊)
差值,求出最小的來,w(T)再加上最小的差值就是次小生成樹了。

給定一個圖,詢問該圖的最小生成樹與次小生成樹是否一致。

Kruscal實現版:

代碼:

//Gang
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define
FOR(x,y,z) for(int x=y;x<=z;x++) #define REP(x,y,z) for(int x=y;x>=z;x--) #define ll long long using namespace std; int t,n,m,fa[10000],num,ans[10000]; int tot,bns,k,answer=99999999; struct node { int x,y,z; } e[101*101]; int cmp(node a,node b) { return a.z<b.z; } int find(int x) {
int p,temp; p=x; while(fa[x]!=x) { x=fa[x]; } while(x!=p) { temp=fa[p]; fa[p]=x; p=temp; } return x; } int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); tot=0,bns=0; answer=99999999; memset(fa,0,sizeof(fa)); memset(ans,0,sizeof(ans)); FOR(i,1,m) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); sort(e+1,e+m+1,cmp); FOR(i,1,n)fa[i]=i; FOR(i,1,m) { int dx=find(e[i].x),dy=find(e[i].y); if(dx!=dy) { tot++; fa[dx]=dy; ans[tot]=i; bns+=e[i].z; } if(tot==n-1)break; } FOR(i,1,tot) { k=0; num=0; FOR(j,1,n) fa[j]=j; sort(e+1,e+m+1,cmp); FOR(j,1,m) { if(j==ans[i])continue; int dx=find(e[j].x),dy=find(e[j].y); if(dx!=dy) { fa[dx]=dy; num++; k+=e[j].z; } if(num==n-1)break; } if(num==n-1)answer=min(k,answer); } if(answer==bns)printf("Not Unique!\n"); else printf("%d\n",bns); } return 0; }

prim實現版

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int inf = 0x7fffffff;
const int size = 501;

int firstpath[size][size];
int secondpath[size][size];
int pre[size];
int d[size];
int tree[size];
int t=0;
bool flag[size];
int V,E;

int qmax(int x,int y)
{
   if(x>y)return x;
   else return y;
}

void prime(int u)
{
   int i,j;
   for(i=1;i<=V;++i)
    {
      flag[i]=false;
      d[i]=inf;
    }
   for(i=1;i<=V;++i)
    for(j=i;j<=V;++j)
     secondpath[i][j]=secondpath[j][i]=-1;
   t=0;
   tree[t++]=u;
   flag[u]=true;

   for(i=1;i<V;++i)
    {
       int min=inf;
       int k;
       for(j=1;j<=V;++j)
        {
           if(d[j]>firstpath[u][j])
            {
              d[j]=firstpath[u][j];
              pre[j]=u;
            }
           if(!flag[j] && d[j]<min)
            {
               min=d[j];
               k=j;
            }
        }

        for(j=0,u=k;j<t;++j)
         {
           secondpath[tree[j]][u]=qmax(secondpath[tree[j]][pre[u]],d[u]);
           secondpath[u][tree[j]]=secondpath[tree[j]][u];
         }
       firstpath[pre[u]][u]=firstpath[u][pre[u]]=inf;
       flag[u]=true;
       tree[t++]=u;
    }

   for(i=1;i<=V;++i)
    for(j=i+1;j<=V;++j)
     if(firstpath[i][j]!=inf && firstpath[i][j]==secondpath[j][i])
      {
        printf("Yes\n");
        return ;
      }
   printf("No\n");
}

int main()
{
   int i,T,j,x,y,z;
   scanf("%d",&T);
   while(T--)
    {
      scanf("%d%d",&V,&E);
      for(i=1;i<=V;++i)
       for(j=i;j<=V;++j)
        firstpath[i][j]=firstpath[j][i]=inf;
      for(i=0;i<E;++i)
       {
          scanf("%d%d%d",&x,&y,&z);
          firstpath[x][y]=firstpath[y][x]=z;
       }
      prime(1);
    }
   return 0;
}

次最小生成樹 模版