uva 10600 ACM Contest And Blackout

题意:

求最小生成树和次小生成树的总权值。

思路:

第一种做法,适用于规模较小的时候,prim算法进行的时候维护在树中两点之间路径中边的最大值,复杂度O(n^2),枚举边O(m),总复杂度O(n^2);

第二种做法,倍增求lca,预处理复杂度O(nlog(n)),替换的时候log(n),总复杂度为O(mlog(n))。

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 using namespace std;
  5 
  6 const int maxn = 105;
  7 const int inf = 0x3f3f3f3f;
  8 
  9 int mp[maxn][maxn];
 10 bool vis[maxn];
 11 bool used[maxn][maxn];
 12 int d[maxn];
 13 int path[maxn][maxn];
 14 int pre[maxn];
 15 
 16 int prim(int n)
 17 {
 18     memset(path,0,sizeof(path));
 19     memset(vis,0,sizeof(vis));
 20     memset(used,0,sizeof(used));
 21     
 22     vis[1] = 1;
 23     d[1] = 0;
 24     
 25     int ans = 0;
 26     
 27     for (int i = 2;i <= n;i++)
 28     {
 29         pre[i] = 1;
 30         d[i]= mp[1][i];
 31     }
 32     
 33     for (int i = 0;i < n - 1;i++)
 34     {
 35         int x = -1,dis = inf;
 36         
 37         for (int j = 1;j <= n;j++)
 38         {
 39             if (!vis[j] && d[j] < dis)
 40             {
 41                 dis = d[j];
 42                 x = j;
 43             }
 44         }
 45         
 46         vis[x] = 1;
 47         used[x][pre[x]] = used[pre[x]][x] = 1;
 48         
 49         ans += dis;
 50         
 51         for (int j = 1;j <= n;j++)
 52         {
 53             if (vis[j] && j != x) path[j][x] = path[x][j] = max(dis,path[j][pre[x]]);
 54             
 55             if (!vis[j] && mp[x][j] < d[j])
 56             {
 57                 d[j] = mp[x][j];
 58                 pre[j] = x;
 59             }
 60         }
 61     }
 62     
 63     return ans;
 64 }
 65 
 66 int main()
 67 {
 68     int t;
 69     
 70     scanf("%d",&t);
 71     
 72     while (t--)
 73     {
 74         int n,m;
 75         
 76         scanf("%d%d",&n,&m);
 77         
 78         memset(mp,inf,sizeof(mp));
 79         
 80         for (int i = 0;i < m;i++)
 81         {
 82             int a,b,c;
 83             
 84             scanf("%d%d%d",&a,&b,&c);
 85             
 86             mp[a][b] = mp[b][a] = min(mp[a][b],c);
 87         }
 88         
 89         int ans1 = prim(n);
 90         
 91         int ans2 = inf;
 92         
 93         for (int i = 1;i <= n;i++)
 94         {
 95             for (int j = i + 1;j <= n;j++)
 96             {
 97                 if (used[i][j]) continue;
 98                 
 99                 ans2 = min(ans2,ans1 - path[i][j] + mp[i][j]);
100             }
101         }
102         
103         printf("%d %d
",ans1,ans2);
104     }
105     
106     return 0;
107 }
原文地址:https://www.cnblogs.com/kickit/p/8808990.html