zoukankan      html  css  js  c++  java
  • 【POJ1697】次小生成树

    题目链接:http://poj.org/problem?id=1679

    题目大意:让你求最小生成树,并判断最小生成树是否唯一。

    解题思路:本题其实是想让你求次小生成树,如果次小生成树和最小生成树权值和相等,最小生成树则不唯一,否则唯一。

    解题步骤:

    1、先求最小生成树,求最小生成树过程中标记出现在最小生成树中的边以及fp[i][j],fp数组保存的是最小生成树上从i到j的最大权值。

    2、枚举所有未出现在最小生成树中的边map[i][j],找到tp=(map[i][j]-fp[i][j])差值最小的进行替换,为什么可以这样?因为加入map[i][j]到最小生成树中后必形成环,然后消去环中非map[i][j]的最大权值边,得到的解必为最优解。

    3、tp==0则最小生成树不唯一,否则唯一。

    View Code
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <vector>
     5 #include <queue>
     6 #include <algorithm>
     7 using namespace std;
     8 
     9 const int maxn=110;
    10 const int oo=0x3fffffff;
    11 int lowcost[maxn], visit[maxn], map[maxn][maxn], used[maxn][maxn], pre[maxn], fp[maxn][maxn]; ///fp数组保存的是最小生成树上从i到j的最大权值边
    12 int n, m, T;
    13 
    14 int Prim()
    15 {
    16     int sum=0;
    17     for(int i=1; i<=n; i++) lowcost[i]=oo, pre[i]=0, visit[i]=0;
    18     lowcost[1]=0;
    19     for(int i=1; i<=n; i++)
    20     {
    21         int k=-1, minn=oo;
    22         for(int j=1; j<=n; j++)
    23             if(minn>lowcost[j]&&!visit[j]) k=j, minn=lowcost[j];
    24         if(k==-1) break;
    25         if(pre[k]!=0)     ///源点不考虑进去
    26         {
    27             used[pre[k]][k]=used[k][pre[k]]=2; ///出现在最小生成树中的边标记一下
    28             for(int j=1; j<=n; j++)
    29                 if(visit[j]) fp[j][k]=max(fp[j][pre[k]],map[pre[k]][k]); ///找生成树中已出现的节点j,求j到k路上最大权值边
    30         }
    31         visit[k]=1;
    32         sum+=lowcost[k];
    33         lowcost[k]=0;
    34         for(int j=1; j<=n; j++)
    35             if(!visit[j]&&lowcost[j]>map[k][j])
    36             {
    37                 pre[j]=k;
    38                 lowcost[j]= map[k][j];
    39             }
    40     }
    41     return sum;
    42 }
    43 
    44 void Solve()
    45 {
    46     int ans=Prim();
    47     int tp=oo;
    48     for(int i=1; i<=n; i++)
    49         for(int j=1; j<=n; j++)
    50            if(used[i][j]==1) tp=min(tp,map[i][j]-fp[i][j]); ///枚举未出现在生成树中的边
    51     if(tp==0) puts("Not Unique!");
    52     else printf("%d\n",ans);
    53 }
    54 
    55 int main()
    56 {
    57     cin >> T;
    58     while(T--)
    59     {
    60         scanf("%d%d",&n,&m);
    61         for(int i=1; i<=n; i++)
    62             for(int j=1; j<=n; j++) fp[i][j]=used[i][j]=0, map[i][j]=oo;
    63         for(int i=0; i<m; i++)
    64         {
    65             int u, v, val;
    66             scanf("%d%d%d",&u,&v,&val);
    67             map[u][v]=map[v][u]=val;
    68             used[u][v]=used[v][u]=1;
    69         }
    70         Solve();
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    C#listbox使用方法
    poj 3894 System Engineer (二分图最大匹配--匈牙利算法)
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 黑白无常
  • 原文地址:https://www.cnblogs.com/kane0526/p/3056399.html
Copyright © 2011-2022 走看看