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 }