zoukankan      html  css  js  c++  java
  • poj 1679 The Unique MST

    次小生成树学习:

    顾名思义,次小生成树,就是将图的所有生成树排序后,权值第二小的生成树。

    次小生成树的朴素求法是很好想的,即首先求出最小生成树,之后枚举最小生成树中的所有边,将当前枚举的边“禁止使用”,在这基础之上再求最小生成树,将所有边枚举之后的结果取最小值,那就是次小生成树。这个算法简单暴力,但是可想而知的复杂度是比较大的,在图是稠密图的时候,复杂度接近O(n^3)。在规模较大的时候不建议使用。

    另一个推荐的求法:在添加最小生成树的边之外的边时,会形成环,这个时候,把在这个环中,且在最小生成树中的边给去掉,这时候就形成了另一个生成树。如何实现这个算法的呢?实际上,对于两个点u,v,我们遍历最小生成树,找出u到v的边中的最大权值的边,用一个数组maxn[u][v]保存起来。当我们往最小生成树中加边时,就直接用w - max[u][v] + 当前添加边的权值,这个式子计算出此时生成树的权值之和。那么maxn[u][v]这个数组是如何求得呢?嗯,bfs,即广度优先搜索,对每一个点都遍历一次生成树,每次更新的值都是当前点到其他点的权值。之后就枚举不在生成树的边进行计算,把每次的结果都保存下来,取最小的,就是次小生成树啦。(或许第k小生成树可以这么求?)这个算法的复杂度为O(n^2)。

    例题:

    https://vjudge.net/problem/POJ-1679

    题意:

    这题问的是最小生成树是否唯一。

    思路:

    那么很显然的,如果说最小生成树不唯一的话,那么最小生成树与次小生成树的权值肯定相等,因为对于在最小生成树中的边来说,至少存在一条不在其中的边,与在其中的边的权值相等,这样才满足不唯一,所以只需要求出次小生成树,判断其与最小生成树是否相等就可以了。

    PS:通过这题还学会了用邻接链表表示图,用vector很方便的,就是把以每个点为起点的边搞到一起就ok。

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <queue>
      6 using namespace std;
      7 
      8 struct node
      9 {
     10     int x,y,w;
     11 } e[6000];
     12 
     13 struct ord
     14 {
     15     int p,dis;
     16 };
     17 
     18 vector<node> v[105];
     19 
     20 int par[105];
     21 int maxn[105][105];
     22 
     23 bool used[6000],vis[6000];
     24 
     25 void init(int n)
     26 {
     27     for (int i = 1;i <= n;i++)
     28         par[i] = i;
     29 }
     30 
     31 int fin(int x)
     32 {
     33     if (x == par[x]) return x;
     34     else return par[x] = fin(par[x]);
     35 }
     36 
     37 void unit(int x,int y)
     38 {
     39     x = fin(x);
     40     y = fin(y);
     41 
     42     if (x != y) par[x] = y;
     43 }
     44 
     45 bool cmp(node aa,node bb)
     46 {
     47     return aa.w < bb.w;
     48 }
     49 
     50 void adde(int x,int y,int dis)
     51 {
     52     node t;
     53     t.x = x;
     54     t.y = y;
     55     t.w = dis;
     56     v[x].push_back(t);
     57 }
     58 
     59 void bfs(int k)
     60 {
     61     memset(used,0,sizeof(used));
     62 
     63     ord now,nex;
     64 
     65     now.p = k;now.dis = 0;
     66     used[k] = true;
     67 
     68     queue<ord> qq;
     69 
     70     while (!qq.empty()) qq.pop();
     71 
     72     qq.push(now);
     73 
     74     while (!qq.empty())
     75     {
     76         //printf("dsfsd
    ");
     77         ord t = qq.front();qq.pop();
     78 
     79         int x = t.p,tmaxn = t.dis;
     80 
     81         for (int i = 0;i < v[x].size();i++)
     82         {
     83             node tt = v[x][i];
     84 
     85             nex.dis = tt.w;nex.p = tt.y;
     86 
     87             if (!used[nex.p])
     88             {
     89                 if (tmaxn > nex.dis) nex.dis = tmaxn;
     90                 used[nex.p] = true;
     91                 maxn[k][nex.p] = nex.dis;
     92                 qq.push(nex);
     93             }
     94         }
     95     }
     96 }
     97 
     98 int main()
     99 {
    100     int t;
    101 
    102     scanf("%d",&t);
    103 
    104     while (t--)
    105     {
    106         int n,m;
    107 
    108         scanf("%d%d",&n,&m);
    109 
    110         init(n);
    111 
    112         memset(v,0,sizeof(v));
    113         memset(vis,0,sizeof(vis));
    114         memset(used,0,sizeof(used));
    115 
    116         for (int i = 0;i < m;i++)
    117         {
    118             scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
    119         }
    120 
    121         sort(e,e+m,cmp);
    122 
    123         int ans = 0;
    124 
    125         for (int i = 0;i < m;i++)
    126         {
    127             int x = e[i].x,y = e[i].y;
    128 
    129             if (fin(x) == fin(y)) continue;
    130 
    131             unit(x,y);
    132 
    133             vis[i] = true;
    134 
    135             ans += e[i].w;
    136 
    137             adde(x,y,e[i].w);
    138             adde(y,x,e[i].w);
    139         }
    140 
    141         for (int i = 1;i <= n;i++)
    142         {
    143             bfs(i);
    144         }
    145 
    146         int minn = 100000000;
    147 
    148         for (int i = 0;i < m;i++)
    149         {
    150             if (!vis[i])
    151             {
    152                 int tans = ans;
    153                 int x = e[i].x,y = e[i].y;
    154 
    155                 tans -= maxn[x][y];
    156 
    157                 tans += e[i].w;
    158 
    159                 if (tans < minn) minn = tans;
    160             }
    161 
    162 
    163         }
    164 
    165         if (minn == ans) printf("Not Unique!
    ");
    166         else printf("%d
    ",ans);
    167     }
    168 
    169     return 0;
    170 }
  • 相关阅读:
    Centos7yum安装LNMP
    CentOS7安装和配置rsync+inotify
    SSH
    nginx https
    nginx rewrite
    nginx代理缓存
    nginx动静分离
    Centos7使用squid实现正向代理
    利用tengine的nginx_upstream_check_module来检测后端服务状态
    nginx基于tcp负载均衡
  • 原文地址:https://www.cnblogs.com/kickit/p/7172379.html
Copyright © 2011-2022 走看看