• POJ 1679 The Unique MST


    题意就是求一个MST,然后求一个次小生成树(可能与MST相等),然后问我们这个次小生成树是否与MST的总权重相等。

    朴素的想法是求出一个MST后把它上面的每个边删一次(一次就够,因为次小生成树如果存在必然与MST有n-1条公共边),删后再求一次MST,然而求 n-1 次 MST明显不实际。

    我们转换一下思路,不是删掉边加边而是替换边,假设加的边是 G[i][j] (没用过的)那么被替换的边一定是MST上 i -> j 的路径中最大的边(否则得到一定不是次小生成树),如此只要在求一次MST的基础上多加O(n^2)。

    为了达到这个目的我们需要用prim在求MST的同时处理处path[i][j]。具体参见代码。

    if(vis[j]&&u!=j)//path[u][j] means the longest edges of the path from u to j
                    path[j][u]=path[u][j]=max(path[j][pre[u]],dist[u]);

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <vector>
      5 #include <utility>
      6 
      7 using namespace std;
      8 #define fst first
      9 #define scd second
     10 #define pb(x) push_back((x))
     11 #define mkp(x,y) make_pair((x),(y)) 
     12 #define ist(x) insert((x))
     13 typedef long long ll;
     14 typedef pair<int ,int > pii;
     15 typedef pair<ll ,ll > pll;
     16 typedef vector< int > vi;
     17 ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
     18 ll qPow(ll a,ll b,ll mod){ ll ret=1ll;while(b){ if(b&1) ret=ret*a%mod;a=a*a%mod;b>>=1;} return ret; }
     19 
     20 const int INF=0x3f3f3f3f;
     21 int n,m;// number of V and E
     22 int G[128][128];
     23 bool vis[128],used[128][128];
     24 int path[128][128],dist[128];
     25 int pre[128];
     26 
     27 int prim(int v){// v is start
     28     memset(vis,false,sizeof(vis));
     29     memset(used,false,sizeof(used));//
     30     memset(path,0,sizeof(path));//
     31     for(int i=1;i<=n;++i){
     32         dist[i]=G[v][i];
     33         pre[i]=v;
     34     }
     35     vis[v]=true;
     36     
     37     int sum=0;
     38     int u,tmp;// u is index of tmp dot
     39     for(int i=1;i<n;++i){// n-1 edges
     40         u=v;
     41         tmp=INF;
     42         for(int j=1;j<=n;++j){// find the nearest vertex
     43             if(!vis[j]&&dist[j]<tmp){
     44                 tmp=dist[j];
     45                 u=j;
     46             }
     47         }
     48         vis[u]=true;
     49         sum+=dist[u];
     50         used[u][pre[u]]=used[pre[u]][u]=true;
     51 
     52         for(int j=1;j<=n;++j){
     53             if(vis[j]&&u!=j)//path[u][j] means the longest edges of the path from u to j
     54                 path[j][u]=path[u][j]=max(path[j][pre[u]],dist[u]);
     55             if(!vis[j]&&dist[j]>G[u][j]){//relax
     56                 dist[j]=G[u][j];
     57                 pre[j]=u;// 
     58             }
     59         }
     60     }
     61     return sum;
     62 }
     63 
     64 int second_MST(int tot) {
     65     int ans=INF;
     66     //puts("test in second_MST:
    ");
     67     for(int i=1;i<=n;++i){
     68         for(int j=1;j<=n;++j){
     69             //printf("%d %d : used=%d , path=%d ,G=%d
    ",i,j,used[i][j]?1:0,path[i][j],G[i][j]);
     70             if(!used[i][j]&&i!=j)
     71             ans=min(ans,tot-path[i][j]+G[i][j]);
     72         }
     73     }
     74     return ans;
     75 }
     76 
     77 int main(){
     78     int Test;
     79     scanf("%d",&Test);
     80     while(Test--) {
     81         scanf("%d%d",&n,&m);
     82         
     83         // initial
     84         for(int i=1;i<=n;++i)
     85             for(int j=1;j<=n;++j) G[i][j]=INF;
     86         
     87         for(int i=0;i<m;++i){
     88             int u,v,w;
     89             scanf("%d%d%d",&u,&v,&w);
     90             G[u][v]=w,G[v][u]=w;
     91         }
     92         
     93         int tot = prim(1);
     94         int ans=second_MST(tot);
     95         //printf("tot and ans : %d , %d
    ",tot,ans);
     96         if(ans==tot) puts("Not Unique!");
     97         else printf("%d
    ",tot);
     98     } 
     99     return 0;
    100 }
    View Code
  • 相关阅读:
    Go学习(5):集合
    Go学习(4):数组和切片
    Go学习(3):分支循环
    Go学习(2):基本语法
    Go学习(1):简介和配置
    input输入框只能输入数字而且开头不能为零
    JS 显示周 几和 月 日
    IntelliJ Idea 跳出括号并且光标移到末尾的快捷键
    不可小视的String字符串
    PrintWriter中的write与println方法居然就是这些区别
  • 原文地址:https://www.cnblogs.com/Kiritsugu/p/9635187.html
Copyright © 2020-2023  润新知