• POJ 1679 The Unique MST:次小生成树【倍增】


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

    题意:

      给你一个图,问你这个图的最小生成树是否唯一。

    题解:

      求这个图的最小生成树和次小生成树。如果相等,则说明不唯一。

      次小生成树(倍增算法):

        maxn[k][i]:表示从节点i向上走2^k步,这一段中边权的最大值。

        枚举每一条不在MST中的边,求出这条边两端点之间在MST上路径上的最大边权mx。

        次小生成树(非严格) = max(MST - mx + len)

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 #include <vector>
      6 #define MAX_N 105
      7 #define MAX_E 10005
      8 #define MAX_K 20
      9 #define INF 1000000000
     10 
     11 using namespace std;
     12 
     13 struct E
     14 {
     15     int s;
     16     int t;
     17     int len;
     18     E(int _s,int _t,int _len)
     19     {
     20         s=_s;
     21         t=_t;
     22         len=_len;
     23     }
     24     E(){}
     25     friend bool operator < (const E &a,const E &b)
     26     {
     27         return a.len<b.len;
     28     }
     29 };
     30 
     31 struct Edge
     32 {
     33     int dest;
     34     int len;
     35     Edge(int _dest,int _len)
     36     {
     37         dest=_dest;
     38         len=_len;
     39     }
     40     Edge(){}
     41 };
     42 
     43 int n,m,t;
     44 int fa[MAX_N];
     45 int dep[MAX_N];
     46 int par[MAX_K][MAX_N];
     47 int maxn[MAX_K][MAX_N];
     48 bool vis[MAX_E];
     49 vector<E> e;
     50 vector<Edge> edge[MAX_N];
     51 
     52 void read()
     53 {
     54     cin>>n>>m;
     55     e.clear();
     56     for(int i=1;i<=n;i++)
     57     {
     58         edge[i].clear();
     59     }
     60     int a,b,v;
     61     for(int i=1;i<=m;i++)
     62     {
     63         cin>>a>>b>>v;
     64         e.push_back(E(a,b,v));
     65     }
     66 }
     67 
     68 void init_union_find()
     69 {
     70     for(int i=1;i<=n;i++)
     71     {
     72         fa[i]=i;
     73     }
     74 }
     75 
     76 int find(int x)
     77 {
     78     return fa[x]==x ? x : fa[x]=find(fa[x]);
     79 }
     80 
     81 void unite(int x,int y)
     82 {
     83     int px=find(x);
     84     int py=find(y);
     85     if(px==py) return;
     86     fa[px]=py;
     87 }
     88 
     89 bool same(int x,int y)
     90 {
     91     return find(x)==find(y);
     92 }
     93 
     94 int kruskal()
     95 {
     96     init_union_find();
     97     sort(e.begin(),e.end());
     98     memset(vis,false,sizeof(vis));
     99     int cnt=0;
    100     int res=0;
    101     for(int i=0;i<e.size() && cnt<n-1;i++)
    102     {
    103         E temp=e[i];
    104         if(!same(temp.s,temp.t))
    105         {
    106             cnt++;
    107             res+=temp.len;
    108             vis[i]=true;
    109             unite(temp.s,temp.t);
    110             edge[temp.s].push_back(Edge(temp.t,temp.len));
    111             edge[temp.t].push_back(Edge(temp.s,temp.len));
    112         }
    113     }
    114     return cnt==n-1 ? res : -1;
    115 }
    116 
    117 void dfs(int now,int p,int d,int l)
    118 {
    119     dep[now]=d;
    120     par[0][now]=p;
    121     maxn[0][now]=l;
    122     for(int i=0;i<edge[now].size();i++)
    123     {
    124         Edge temp=edge[now][i];
    125         if(temp.dest!=p) dfs(temp.dest,now,d+1,temp.len);
    126     }
    127 }
    128 
    129 void init_lca()
    130 {
    131     dfs(1,-1,0,-1);
    132     for(int k=0;k+1<MAX_K;k++)
    133     {
    134         for(int i=1;i<=n;i++)
    135         {
    136             if(par[k][i]==-1)
    137             {
    138                 par[k+1][i]=-1;
    139                 maxn[k+1][i]=-1;
    140             }
    141             else
    142             {
    143                 par[k+1][i]=par[k][par[k][i]];
    144                 maxn[k+1][i]=max(maxn[k][i],maxn[k][par[k][i]]);
    145             }
    146         }
    147     }
    148 }
    149 
    150 int cal_max(int a,int b)
    151 {
    152     if(dep[a]>dep[b]) swap(a,b);
    153     int res=-1;
    154     for(int k=0;k<=MAX_K && dep[a]!=dep[b];k++)
    155     {
    156         if(((dep[b]-dep[a])>>k)&1)
    157         {
    158             res=max(res,maxn[k][b]);
    159             b=par[k][b];
    160         }
    161     }
    162     if(a==b) return res;
    163     for(int k=MAX_K-1;k>=0;k--)
    164     {
    165         if(par[k][a]!=par[k][b])
    166         {
    167             res=max(res,maxn[k][a]);
    168             res=max(res,maxn[k][b]);
    169             a=par[k][a];
    170             b=par[k][b];
    171         }
    172     }
    173     return max(res,maxn[0][a]);
    174 }
    175 
    176 int sst(int mst)
    177 {
    178     if(mst==-1) return -1;
    179     init_lca();
    180     int ans=INF;
    181     for(int i=0;i<e.size();i++)
    182     {
    183         if(!vis[i])
    184         {
    185             E temp=e[i];
    186             int mx=cal_max(temp.s,temp.t);
    187             ans=min(ans,mst-mx+temp.len);
    188         }
    189     }
    190     return ans==INF ? -1 : ans;
    191 }
    192 
    193 void work()
    194 {
    195     int mst=kruskal();
    196     if(mst==sst(mst)) cout<<"Not Unique!"<<endl;
    197     else cout<<mst<<endl;
    198 }
    199 
    200 int main()
    201 {
    202     cin>>t;
    203     while(t--)
    204     {
    205         read();
    206         work();
    207     }
    208 }
  • 相关阅读:
    使用NPOI读取Excel表格内容并进行修改
    JSON.parse()和JSON.stringify()
    切图时图片的选择:JPG、PNG、GIF的区别
    用js把数据从一个页面传到另一个页面
    iframe中positioin:fixed失效问题
    YUV格式&像素
    JS中插入节点的方法appendChild和insertBefore的应用
    CSS的相对定位和就对定位
    CSS中的相对定位和绝对定位
    POJ-1734
  • 原文地址:https://www.cnblogs.com/Leohh/p/8072552.html
Copyright © 2020-2023  润新知