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 }

 

posted @ 2020-02-17 20:03  AaronChang  阅读(156)  评论(0编辑  收藏  举报