zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营6 I.导航系统 (最小生成树)

    https://ac.nowcoder.com/acm/contest/3007/I

    题中给定的图必定是一棵树    

    容易发现,如果将输入的N(N-1)个距离看做N(N-1)条无向边的话,那么如果数据合法,原树就是这张新图的最小生成树。
    证明:由于边权是非负的,可以考虑Kruskal算法的过程,每一次引入的边都是尽可能短的,所以一定是树中的边,通过简单的归纳即证。
     
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 505;
     5 int n,m,s,cnt;
     6 struct edge{
     7     int from,to,w;
     8     bool operator < (const edge &b) const{
     9         return w < b.w;
    10     }
    11 }e[maxn*maxn];
    12 struct node{
    13     int u,v,w;
    14     bool operator < (const node &b) const{
    15         return w<b.w;
    16     }
    17 };
    18 struct Node{
    19     vector<int> v;
    20     vector<int> w;
    21 }g[maxn];
    22 int fa[maxn],dis[maxn][maxn];
    23 vector<node> ans;
    24 int get(int x){
    25     if(x == fa[x]) return x;
    26     return fa[x] = get(fa[x]);
    27 }
    28 void merge(int x,int y){
    29     int u = get(x),v = get(y);
    30     if(u == v) return;
    31     fa[u] = v;
    32 }
    33 void kruskal(){
    34     sort(e+1,e+1+m);
    35     for(int i = 1;i<=n;i++) fa[i] = i;
    36     for(int i = 1;i<=m;i++){
    37         int x = get(e[i].from );
    38         int y = get(e[i].to );
    39         if(x == y) continue;
    40         merge(x,y);
    41         ans.push_back({e[i].from,e[i].to,e[i].w});
    42     }
    43 }
    44 void addedge(int x,int y,int c){
    45     e[cnt].from = x,e[cnt].to = y,e[cnt].w = c;
    46     cnt++;
    47 }
    48 int vis[maxn],siz[maxn];
    49 void dfs(int cur,int pos){//只需求出一个点到各个点的最小距离即可进行判断
    50     vis[cur] = 1;
    51     siz[cur] = pos;
    52     for(int i = 0;i<g[cur].v.size();i++){
    53         int v = g[cur].v[i];
    54         if(!vis[v]) dfs(v,pos+g[cur].w[i]);
    55     }
    56 }
    57 int main(){
    58     cin>>n;
    59     m = n*(n-1),cnt = 1;;
    60     for(int i = 1;i<=n;i++){
    61         for(int j = 1;j<=n;j++){
    62             cin>>dis[i][j];
    63             if(i == j) continue;
    64             addedge(i,j,dis[i][j]);
    65         }
    66     }
    67     kruskal();
    68     for(int i = 0;i<ans.size();i++){//建一个新图
    69         node t = ans[i];
    70         g[t.u].v.push_back(t.v);
    71         g[t.v].v.push_back(t.u);
    72         g[t.u].w.push_back(t.w);
    73         g[t.v].w.push_back(t.w);
    74     }
    75     for(int i = 1;i<=n;i++){
    76         if(g[i].v.size() == 1 ) {
    77             s = i;break;
    78         }
    79     }
    80     dfs(s,0);
    81     for(int i = 1;i<=n;i++){
    82         if(siz[i]!=dis[s][i]){
    83             cout<<"No";return 0;
    84         }
    85     }
    86     sort(ans.begin(),ans.end());
    87     cout<<"Yes"<<endl;
    88     for(int i = 0;i<ans.size();i++){
    89         cout<<ans[i].w<<endl;
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    用位运算实现十进制转换为二进制
    【Zhejiang University PATest】02-3. 求前缀表达式的值
    【Zhejiang University PATest】02-1. Reversing Linked List
    【Tsinghua OJ】隧道(Tunel)问题
    冒泡排序及其优化
    有序向量的查找算法
    【Tsinghua OJ】灯塔(LightHouse)问题
    有序向量的去重算法
    【Tsinghua OJ】祖玛(Zuma)问题
    倒水问题(《怎样解题》中的经典问题)
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12323310.html
Copyright © 2011-2022 走看看