1. 程式人生 > >poj The Unique MST 次小生成樹(入門級)

poj The Unique MST 次小生成樹(入門級)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 105
const int INF=0x3f3f3f3f;
int g[MAX][MAX],dist[MAX],mmax[MAX][MAX];  ///g儲存地圖  dist儲存從起點到其餘各點的距離 maxn儲存從i到j的最大邊權值
int pre[MAX]; ///pre儲存j的離它最近的是哪個點
bool mark[MAX]; ///相當於vis  用來標記該點是否已經用過
bool connect[MAX][MAX]; ///儲存i-j的那條邊是否加入了最小生成樹  false 加入 true  沒有
int mst,mint; ///mst儲存最小生成樹的權值和
int n,m;
int prim()
{
       int res=0,fa,p,min,i,j;
       memset(mmax,0,sizeof(mmax));
       for(i=1;i<=n;i++)
       {
              dist[i]=g[1][i];
              pre[i]=1;
              mark[i]=false;
       }
       dist[1]=0;
       mark[1]=true;
       for(i=1;i<n;i++)
       {
              p=-1;min=INF;
              for(j=1;j<=n;j++)
              {
                     if(!mark[j]&&dist[j]<min)
                     {
                            p=j;
                            min=dist[j];
                     }
              }
              if(p==-1) return res;
              mark[p]=true;
              res+=dist[p];
              fa=pre[p]; ///找到離p最近的點
              connect[fa][p]=false;
              connect[p][fa]=false;
              mmax[fa][p]=min;
              ///遍歷所有的點 求其餘點到p的最大權值
              for(j=1;j<=n;j++)
                     mmax[j][p]=(mmax[fa][p]>mmax[j][fa])?mmax[fa][p]:mmax[j][fa];
              for(j=1;j<=n;j++)
              {
                     if(!mark[j]&&dist[j]>g[p][j])
                     {
                            dist[j]=g[p][j];
                            pre[j]=p;
                     }
              }
       }
       return res;
}

int main()
{
       int tc;
       scanf("%d",&tc);
       while(tc--)
       {
              scanf("%d %d",&n,&m);
              memset(g,INF,sizeof(g));
              memset(connect,false,sizeof(connect));
              while(m--)
              {
                     int u,v,c;
                     scanf("%d %d %d",&u,&v,&c);
                     g[u][v]=c;
                     g[v][u]=c;
                     connect[u][v]=true;
                     connect[v][u]=true;
              }
              mst=prim();
              int i,j;
              bool flag=false;
              for(i=1;i<=n;i++)
                     for(j=1;j<=n;j++)
                     {
                            ///如果i-j這條邊加入了最小生成樹 或者i-j這條路不通  continue
                            if(connect[i][j]==false||g[i][j]==INF)
                                   continue;
                            ///如果加入的邊和刪除的邊的大小是一樣的  說明次小生成樹的權值和等於最小生成樹的權值和
                            ///也就是說最小生成樹不唯一
                            if(g[i][j]==mmax[i][j])
                            {
                                   flag=true;
                                   break;
                            }
                     }
              if(flag)
                     printf("Not Unique!\n");
              else
                     printf("%d\n",mst);
       }
       return 0;
}