zoukankan      html  css  js  c++  java
  • poj 1679 判断MST是不是唯一的 (次小生成树)

    判断MST是不是唯一的 如果是唯一的 就输出最小的权值和 如果不是唯一的 就输出Not Unique!

    次小生成树就是第二小生成树  如果次小生成树的权值和MST相等  那么MST就不是唯一的

    法一:

    先求出最小的权值和 然后一条边一条边的删
    先标记MST中所使用的边 删边就是屏蔽这条边后 再对剩下的边(不管这些边是否被标记)求MST 如果最后的权值和 与开始算出的最小的那个 相等 就说明不是唯一的

    Sample Input

    2 //T
    3 3 //n m
    1 2 1// u v w
    2 3 2
    3 1 3
    4 4
    1 2 2
    2 3 2
    3 4 2
    4 1 2
    Sample Output

    3
    Not Unique!

    Kruskal

      1 # include <iostream>
      2 # include <cstdio>
      3 # include <cstring>
      4 # include <algorithm>
      5 # include <cmath>
      6 # define LL long long
      7 using namespace std ;
      8 
      9 int n ;
     10 const int MAXN=110;//最大点数
     11 const int MAXM=10000;//最大边数
     12 int F[MAXN];//并查集使用
     13 int del[MAXM] ;
     14 struct Edge
     15 {
     16     int u,v,w;
     17     int tag ;
     18 }edge[MAXM];//存储边的信息,包括起点/终点/权值
     19 
     20 int tol;//边数,加边前赋值为0
     21 void addedge(int u,int v,int w)
     22 {
     23 
     24     edge[tol].u=u;
     25     edge[tol].v=v;
     26     edge[tol].tag = 0 ;
     27     edge[tol++].w=w;
     28 }
     29 bool cmp(Edge a,Edge b)
     30 {//排序函数,讲边按照权值从小到大排序
     31     return a.w<b.w;
     32 }
     33 int find(int x)
     34 {
     35     if(F[x]==-1)return x;
     36     else return F[x]=find(F[x]);
     37 }
     38 int Kruskal(int d)//传入点数,返回最小生成树的权值,如果不连通返回-1
     39 {
     40     memset(F,-1,sizeof(F));
     41 
     42     int cnt=0;//计算加入的边数
     43     int ans=0;
     44     for(int i=0;i<tol;i++)
     45     {
     46         if (i == d)  //屏蔽id为d的这一条边
     47             continue ;
     48         int u=edge[i].u;
     49         int v=edge[i].v;
     50         int w=edge[i].w;
     51         int t1=find(u);
     52         int t2=find(v);
     53         if(t1!=t2)
     54         {
     55             ans+=w;
     56             F[t1]=t2;
     57             cnt++;
     58             edge[i].tag = 1 ;
     59         }
     60         if(cnt==n-1)break;
     61     }
     62     if(cnt<n-1)return -1;//不连通
     63     else return ans;
     64 }
     65 
     66 int main()
     67 {
     68 
     69    // freopen("in.txt","r",stdin) ;
     70     int m ;
     71     int T ;
     72     scanf("%d" , &T) ;
     73     while(T--)
     74     {
     75         scanf("%d %d" , &n , &m) ;
     76         int i ;
     77         int u , v , w ;
     78         tol = 0 ;
     79         while(m--)
     80         {
     81             scanf("%d %d %d" , &u , &v , &w) ;
     82             addedge(u , v , w) ;
     83         }
     84 
     85         sort(edge,edge+tol,cmp);
     86         int ans = Kruskal(-1) ;
     87 
     88         int k = 0 ;
     89         for (i = 0 ; i < tol ; i++)
     90         {
     91             if (edge[i].tag == 1 )
     92             {
     93                 del[k] = i ;
     94                 k++ ;
     95             }
     96         }
     97         bool flag = 0 ;
     98         int t_ans ;
     99         for (i = 0 ; i < k ; i++)
    100         {
    101             t_ans = Kruskal(del[i]) ;
    102             if (t_ans == ans)
    103             {
    104                 flag = 1 ;
    105                 break ;
    106             }
    107         }
    108         if (flag)
    109             printf("Not Unique!
    ") ;
    110         else
    111             printf("%d
    " , ans) ;
    112 
    113     }
    114     return 0 ;
    115 }
    View Code

    法二 : Prim  

      1 /*
      2  * 次小生成树
      3  * 求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权
      4  * 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案
      5  * 点的编号从0开始
      6  */
      7 # include <iostream>
      8 # include <cstdio>
      9 # include <cstring>
     10 # include <algorithm>
     11 # include <cmath>
     12 # define LL long long
     13 using namespace std ;
     14 
     15 int n ;
     16 const int MAXN=110;
     17 const int INF=0x3f3f3f3f;
     18 bool vis[MAXN];
     19 int lowc[MAXN];
     20 int pre[MAXN];
     21 int Max[MAXN][MAXN];//Max[i][j]表示在最小生成树中从i到j的路径中的最大边权
     22 bool used[MAXN][MAXN];
     23 int cost[MAXN][MAXN];
     24 int Prim()
     25 {
     26     int ans=0;
     27     memset(vis,false,sizeof(vis));
     28     memset(Max,0,sizeof(Max));
     29     memset(used,false,sizeof(used));
     30     vis[0]=true;
     31     pre[0]=-1;
     32     for(int i=1;i<n;i++)
     33     {
     34         lowc[i]=cost[0][i];
     35         pre[i]=0;
     36     }
     37     lowc[0]=0;
     38     for(int i=1;i<n;i++)
     39     {
     40         int minc=INF;
     41         int p=-1;
     42         for(int j=0;j<n;j++)
     43             if(!vis[j]&&minc>lowc[j])
     44             {
     45                 minc=lowc[j];
     46                 p=j;
     47             }
     48         if(minc==INF)return -1;
     49         ans+=minc;
     50         vis[p]=true;
     51         used[p][pre[p]]=used[pre[p]][p]=true;
     52         for(int j=0;j<n;j++)
     53         {
     54             if(vis[j])Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]);
     55             if(!vis[j]&&lowc[j]>cost[p][j])
     56             {
     57                 lowc[j]=cost[p][j];
     58                 pre[j]=p;
     59             }
     60         }
     61     }
     62     return ans;
     63 }
     64 
     65 int smst(int ans)
     66 {
     67     int Min=INF;
     68     for(int i=0;i<n;i++)
     69         for(int j=i+1;j<n;j++)
     70             if(cost[i][j]!=INF && !used[i][j])
     71             {
     72                 Min=min(Min,ans+cost[i][j]-Max[i][j]);
     73             }
     74     if(Min==INF)return -1;//不存在
     75     return Min;
     76 }
     77 
     78 int main()
     79 {
     80    // freopen("in.txt","r",stdin) ;
     81     int T;
     82     int m;
     83     scanf("%d",&T);
     84     while(T--)
     85     {
     86         scanf("%d%d",&n,&m);
     87         int u,v,w;
     88         for(int i=0;i<n;i++)
     89             for(int j=0;j<n;j++)
     90             {
     91                 if(i==j)cost[i][j]=0;
     92                 else cost[i][j]=INF;
     93             }
     94         while(m--)
     95         {
     96             scanf("%d%d%d",&u,&v,&w);
     97             u--;v--;
     98             cost[u][v]=cost[v][u]=w;
     99         }
    100         int ans=Prim();
    101         if(ans==-1)
    102         {
    103             printf("Not Unique!
    ");
    104             continue;
    105         }
    106         if(ans==smst(ans))printf("Not Unique!
    ");
    107         else printf("%d
    ",ans);
    108     }
    109     return 0;
    110 }
    View Code
  • 相关阅读:
    R语言对苏格兰独立民意调查的Meta分析
    R语言中固定与随机效应Meta分析
    Comet OJ
    luoguP6070 [MdOI2020] Decrease 贪心+二维差分
    luoguP6071 [MdOI2020] Treequery DFS序+主席树
    AT2064 [AGC005F] Many Easy Problems 容斥+NTT
    BZOJ 4650: [Noi2016]优秀的拆分 后缀自动机+启发式合并+线段树合并
    BZOJ 1498: [NOI2006]神奇的口袋 性质分析+高精度
    BZOJ 1819: [JSOI]Word Query电子字典 搜索+trie
    robotframework 随机选中下拉框中的值
  • 原文地址:https://www.cnblogs.com/mengchunchen/p/4582194.html
Copyright © 2011-2022 走看看