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 }
  • 相关阅读:
    软件工程二人组队开发第一周
    软件工程第五周
    这学期的目标
    软件工程第四周的总结
    二维数组的最大子数组和 时间复杂度:O(n的四次方)
    10.tesseract
    mysql存储过程和函数
    mysql触发器
    9.selenium
    mysql练习
  • 原文地址:https://www.cnblogs.com/kane0526/p/3056399.html
Copyright © 2011-2022 走看看