Problem:
Problem G:
Network Mess
Gilbert is the network admin of Ginkgo company. His boss is mad about the messy network
cables on the floor. He finally walked up to Gilbert and asked the lazy network admin to illustrate
how computers and switches are connected. Since he is a programmer, he is very reluctant to
move throughout the office and examine cables and switches with his eyes. He instead opted
to get this job done by measurement and a little bit of mathematical thinking, sitting down in
front of his computer all the time. Your job is to help him by writing a program to reconstruct
the network topology from measurements.
There are a known number of computers and an unknown number of switches. Each computer
is connected to one of the switches via a cable and to nothing else. Specifically, a computer
is never connected to another computer directly, or never connected to two or more switches.
Switches are connected via cables to form a tree (a connected undirected graph with no cycles).
No switches are ‘useless.’ In other words, each switch is on the path between at least one pair
of computers.
All in all, computers and switches together form a tree whose leaves are computers and whose
internal nodes switches (See Figure 9).
Gilbert measures the distances between
all pairs of computers
. The distance between two com-
puters is simply the number of switches on the path between the two, plus one. Or equivalently,
it is the number of cables used to connect them. You may wonder how Gilbert can actually
obtain these distances solely based on measurement. Well, he can do so by a very sophisticated
statistical processing technique he invented. Please do not ask the details.
You are therefore given a matrix describing distances between leaves of a tree. Your job is to
construct the tree from it.
Input
The input is a series of distance matrices, followed by a line consisting of a single '
0
'. Each
distance matrix is formatted as follows.
N
a
11
a
12
...
a
1
N
a
21
a
22
...
a
2
N
.   .  .      .
 .   .    .    .
 .   .      .  .
a
N
1
a
N
2
...
a
N
N
N
is the size, i.e. the number of rows and the number of columns, of the matrix.
a
ij
gives the
distance between the
i
-th leaf node (computer) and the
j
-th. You may assume 2 ≤
N
≤ 50 and
the matrix is symmetric whose diagonal elements are all zeros. That is,
a
ii
= 0 and
a
ij
=
a
ji
for each
i
and
j
. Each non-diagonal element
a
ij
(
i
≠
j
) satisfies 2 ≤
a
ij
≤ 30. You may assume
there is always a solution. That is, there is a tree having the given distances between leaf nodes.
Output
For each distance matrix, find a tree having the given distances between leaf nodes. Then output
the degree of each internal node (i.e. the number of cables adjoining each switch), all in a single
line and in ascending order. Numbers in a line should be separated by a single space. A line
should not contain any other characters, including trailing spaces.
Sample Input
4
   0  2  2  2
   2  0  2  2
   2  2  0  2
   2  2  2  0
4
   0
...(truncated)

Submitted solutions:

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

const int MAX_V = 50 *  30;
const int IINF = INT_MAX;

struct Edge { int src,dst; };
vector<Edge> G[MAX_V];
vector<int> computer;
int n,V,mat[61][61];

void dfs(int cur,int prev,int depth,vector<int> &mindist){

  rep(i,computer.size()) {
    if( computer[i] == -1 ) break;
    assert( i < mindist.size() );
    if( cur == computer[i] ) { assert( mindist[i] == IINF); mindist[i] = depth; }
  }

  rep(i,G[cur].size()){
    int next = G[cur][i].dst;
    if( next == prev ) continue;
    dfs(next,cur,depth+1,mindist);
  }

}

void compute(){
  computer.clear();
  computer.resize(n,-1);
  computer[0] = 0;
  V = 1;
  REP(i,1,n) {
    bool update = false; // for debug
    rep(candidate,V) {
      vector<int> mindist(i,IINF);
      dfs(candidate,-1,0,mindist);
      assert( mindist[0] != IINF );
      int add_length = -1;
      rep(j,i){
        int length = mat[i][j] - mindist[j];
        if( length <= 0 ) { add_length = -1; break; }
        if( add_length == -1 ) add_length = length;
        else if( add_length != length ) { add_length = -1; break; }
      }
      if( add_length != -1 ) {
        // add_length ????????????????????????
        // ????????????????????????????????? i ?????????????????\??????
        int prev = candidate;
        rep(k,add_length){
          G[prev].push_back((Edge){prev,V});
          G[V].push_back((Edge){V,prev});
          prev = V;
          ++V;
        }
        computer[i] = V-1;
        update = true;
        break;
      }
    }
    assert( update );
  }
  set<int> S;
  rep(i,n) S.insert(computer[i]);
  vector<int> answer;
  rep(i,V) if( !S.count(i) ) answer.push_back(G[i].size());
  sort(answer.begin(),answer.end());
  rep(i,answer.size()){
    if( i ) printf(" ");
    printf("%d",answer[i]);
  } puts("");
}

int main(){
  while( scanf("%d",&n), n ){
    rep(i,MAX_V) G[i].clear();
    rep(i,n) rep(j,n) scanf("%d",&mat[i][j]);
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1308
final_rank: 2

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

const int MAX_V = 50 * 50 * 30;
const int IINF = INT_MAX;

struct Edge { int src,dst; };
vector<Edge> G[MAX_V];
vector<int> computer;
int n,V,mat[61][61];

void dfs(int cur,int prev,int depth,vector<int> &mindist){

  rep(i,computer.size()) {
    if( computer[i] == -1 ) break;
    assert( i < mindist.size() );
    if( cur == computer[i] ) { assert( mindist[i] == IINF); mindist[i] = depth; }
  }

  rep(i,G[cur].size()){
    int next = G[cur][i].dst;
    if( next == prev ) continue;
    dfs(next,cur,depth+1,mindist);
  }

}

void compute(){
  computer.clear();
  computer.resize(n,-1);
  computer[0] = 0;
  V = 1;
  REP(i,1,n) {
    bool update = false; // for debug
    rep(candidate,V) {
      vector<int> mindist(i,IINF);
      dfs(candidate,-1,0,mindist);
      assert( mindist[0] != IINF );
      int add_length = -1;
      rep(j,i){
        int length = mat[i][j] - mindist[j];
        if( length <= 0 ) { add_length = -1; break; }
        if( add_length == -1 ) add_length = length;
        else if( add_length != length ) { add_length = -1; break; }
      }
      if( add_length != -1 ) {
        // add_length ????????????????????????
        // ????????????????????????????????? i ?????????????????\??????
        int prev = candidate;
        rep(k,add_length){
          G[prev].push_back((Edge){prev,V});
          G[V].push_back((Edge){V,prev});
          prev = V;
          ++V;
        }
        computer[i] = V-1;
        update = true;
        break;
      }
    }
    assert( update );
  }
  set<int> S;
  rep(i,n) S.insert(computer[i]);
  vector<int> answer;
  rep(i,V) if( !S.count(i) ) answer.push_back(G[i].size());
  sort(answer.begin(),answer.end());
  rep(i,answer.size()){
    if( i ) printf(" ");
    printf("%d",answer[i]);
  } puts("");
}

int main(){
  while( scanf("%d",&n), n ){
    rep(i,MAX_V) G[i].clear();
    rep(i,n) rep(j,n) scanf("%d",&mat[i][j]);
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3032
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
int cost[2500*30][52];
int cnt = 0;
int N;
int A[52][51];
vector<int>G[2500*30];
void connect(int x,int y,int num){
  int p = x;
  for(int i=0;i<num-1;i++){
    G[p].push_back( cnt );
    G[cnt].push_back( p );
    p = cnt++;
  }
  G[p].push_back( y );
  G[y].push_back( p );
}

void update(int id){
  queue<int> q;
  q.push( id );
  cost[id][id] = 0;
  while( !q.empty() ){
    int p = q.front();  q.pop();
    for(int i=0;i<(int)G[p].size();i++){
      int to = G[p][i];
      if( cost[to][id] == -1 ) {
        cost[to][id] = cost[p][id]+1;
        //         cout <<"cost " <<  to << " "<<id<< " "<< cost[to][id] << endl;
        q.push( to );
      }
    }
  }
}

int check(int x,int y){
  int c = A[x][0];
  int pc = cost[y][0];
  int comp = c - pc;
  //  cout << "check " << x << " "<< y << endl;
  // cout << c << " "<< pc << " " << comp << endl;
  if( pc < 0 || comp < 1 ) return 0;
  for(int i=1;i<x;i++){
    c = A[x][i];
    pc = cost[y][i];
    //cout << i << " : " << c << " "<< pc << " " << c - pc << endl;
    if( comp != c - pc ) return 0;
  }
  return comp;
}

void solve(){
  connect(0,1,A[0][1]);
  for(int i=2;i<N;i++){
    memset(cost,-1,sizeof(cost));
    for(int j=0;j<i;j++) update(j);
    for(int j=N;j<cnt;j++){
      int sc = check(i,j);
      if( sc ) {
        connect(i,j,sc);
        break;
      }
    }
  }
}

int main(){
  while(cin >> N&&N){
    for(int i=0;i<N;i++)
      for(int j=0;j<N;j++)
        cin >> A[i][j];      
    cnt = N;
    solve();
    vector<int> ans;

    /* 
    cout << "debug " << endl;
    for(int i=0;i<cnt;i++){
      cout << "node : " << i << endl;
      for(int j=0;j<(int)G[i].size();j++){
        cout << " - > " << G[i][j] << endl;
      }
    }
    */

    for(int i=0;i<N;i++) G[i].clear();
    for(int i=N;i<cnt;i++){
      ans.push_back(G[i].size());
      G[i].clear();
    }
    sort(ans.begin(),ans.end());
    for(int i=0;i<(int)ans.size();i++){
      if( i ) cout << " ";
      cout << ans[i];
    }
    cout << endl;
  }

}
accuracy: 1
time_ms: 240
memory_kb: 18260
final_rank: 6

code_snippet: #include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;

typedef vector<int> Node;
typedef vector<Node> Graph;

const int INF = 1000000000;

int add(Graph& G, int u){
    int v = G.size();
    G[u].push_back(v);
    G.push_back(Node());
    G[v].push_back(u);
    return v;
}
void bellman_ford(const Graph& G, int s, int dist[1000]){
    dist[s] = 0;
    bool update = true;
    while(update){
        update = false;
        for(int i = 0; i < G.size(); i++){
            for(int j = 0; j < G[i].size(); j++){
                int k = G[i][j];
                if(dist[k] > dist[i] + 1){
                    dist[k] = dist[i] + 1;
                    update = true;
                }
            }
        }
    }
}

int main(){
    int N;
    while(cin >> N && N){
        int d[100][100] = {};
        int dist[100][1000] = {};
        REP(i, 100) fill(dist[i], dist[i] + 1000, INF);
        int start[100] = {};
        REP(i, N) REP(j, N) cin >> d[i][j];
        REP(i, N) REP(j, N) d[i][j] -= 2;

        Graph G;
        G.push_back(Node());
        start[0] = 0;
        dist[0][0] = 0;

        for(int i = 1; i < N; i++){
            vector<int> v;
            for(int j = 0; j < i; j++){
                v.push_back(d[i][j]);
            }

            int u = -1;
            int len = -1;
            for(int j = 0; j < G.size(); j++){
                set<int> s;
                for(int k = 0; k < v.size(); k++){
                    s.insert(v[k] - dist[k][j]);
                }
                if(s.size() == 1){
                    u = j;
                    len = *s.begin();
                }
            }

            assert(u != -1);
            assert(len >= 0);
            while(len--){
                u = add(G, u);
            }
            start[i] = u;
            //printf("start[%d] = %d\n", i, u);

            for(int j = 0; j <= i; j++){
                bellman_ford(G, start[j], dist[j]);
            }
        }
        vector<int> ans;
        for(int i = 0; i < G.size(); i++){
            ans.push_back(G[i].size());
        }
        for(int i = 0; i < N; i++){
            ans[ start[i] ]++;
        }
        sort(ans.begin(), ans.end());
        for(int i = 0; i < ans.size(); i++){
            cout << ans[i];
            if(i == ans.size() - 1) cout << endl;
            else cout << " ";
        }
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1720
final_rank: 3

code_snippet: #include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define MAX 50
#define NMAX 80

class Node{
    public:
    vector<int> adjList;
    Node(){}
    void insert( int i ){ adjList.push_back(i);}
};

class Network{
    public:
    vector<Node> nodes;
    Network(){}

    int size(){ return nodes.size(); }
    void addNode(){ nodes.push_back(Node()); }

    void connect( int i, int j ){
        nodes[i].insert(j); nodes[j].insert(i);
    }

    void addNewNodes( int target, int diff, int u ){
        if ( diff == 1 ){
            connect( target, u );
        } else {
            for ( int i = 1; i < diff; i++ ){
                addNode();
                if ( i == 1 ) connect( target, size()-1 );
                else connect( size()-2, size()-1);
            }
            connect( size()-1, u );
        }
    }
};

class State{
    public:
    int cur, pre, d;
    State(){}
    State(int cur, int pre, int d): cur(cur), pre(pre), d(d){}
};

int N, M[MAX][MAX];
Network network;

int getDistance(int s, int t){
    queue<State> Q;
    Q.push(State(s, -1, 0));
    State u;
    while( !Q.empty() ){
        u = Q.front(); Q.pop();
        if ( u.cur == t ) return u.d;
        for ( int i = 0; i < network.nodes[u.cur].adjList.size(); i++ ){
            int v = network.nodes[u.cur].adjList[i];
            if ( v != u.pre ){
                Q.push(State(v, u.cur, u.d + 1));
           }
        }
    }
}

int parse( int source, int end ){
    int pre = M[end+1][0] - getDistance( source, 0 );
    int d;
    for ( int t = 1; t <= end; t++ ){
        d = M[end+1][t] - getDistance( source, t );
        if ( pre != d ) return -1;
    }
    return pre;
}

void addNewNode( int u ){
    for ( int target = N; target < network.size(); target++ ){
        int diff = parse(target, u - 1);
        if ( diff > 0 ) {
            network.addNewNodes(target, diff, u);
            return;
        }
    }
}

void solve(){
    network = Network();
    for ( int i = 0; i < N + 1; i++ ) network.addNode();
    network.connect( 0, network.size()-1);

    for ( int i = 1; i < N; i++ ) addNewNode(i);

    vector<int> degree;
    for ( int i = N; i < network.size(); i++ ) {
        degree.push_back(network.nodes[i].adjList.size());
    }
    sort(degree.begin(), degree.end());
    for ( int i = 0; i < degree.size(); i++ ){
        if ( i ) cout << " ";
        cout << degree[i];
    }
    cout << endl;
}

bool input(){
    cin >> N;
    if ( N == 0 ) return false;
    for ( int i = 0; i < N; i++ ){
        for ( int j = 0; j < N; j++ ) cin >> M[i][j];
    }
    return true;
}
 main(){
    while ( input() ) solve();
 }
accuracy: 1
time_ms: 10
memory_kb: 1296
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;

#define MAX 1000

int n, m; //ツノ-ツドツ青? ツδ?ツタツ青?
int a[52][52];
int dist[MAX][MAX]; //ツδ?ツタiツつゥツづァツノ-ツドjツづ慊づ?づ個仰猟猟」
int cnt[MAX]; //ツδ?ツタiツづ個篠淞青?
int near[MAX]; //ツノ-ツドツづ個暗ェツ氾板凝淞つュツづ可つ?づゥツδ?ツタツづ個氾板債?
bool used[MAX];

vector<int> t[MAX];

void init(){
  m = 0;
  memset(dist, -1, sizeof(dist));
  memset(cnt, 0, sizeof(cnt));
  memset(near, -1, sizeof(near));

  for(int i = 0; i < MAX; i++){
    t[i].clear();
  }

  near[0] = 0;
  near[1] = a[0][1] - 2;

  //1ツ妥、ツ姪堋づ?ツ妥、ツ姪堋づ個甘板つセツつッツ陛環渉按猟?
  for(int i = 0; i < a[0][1] - 1; i++){
    cnt[i] = 2;
    dist[i][0] = i + 1;
    dist[i][1] = a[0][1] - dist[i][0];
    m++;

    if(i < a[0][1] - 2){
      t[i].push_back(i + 1);
      t[i + 1].push_back(i);
    }
  }
}

void show(){
  cout<<"---------------------------------------------\n";
  cout<<"--dist table---------------------------------\n";
  for(int i = 0; i < m; i++){
    for(int j = 0; j < n; j++){
      printf("%3d", dist[i][j]);
    }

    cout<<"    ";
    printf("%3d",cnt[i]);
    cout<<endl;
  }

  cout<<"--near router--------------------------------\n";
  for(int i = 0; i < n; i++){
    cout << "node " << i<<" : ";
    cout << near[i] << endl;
  }

  cout<<"--router graph-------------------------------\n";

  for(int i = 0; i < m; i++){
    cout<<i<<" : ";
    for(int j = 0; j < t[i].size(); j++){
      cout << t[i][j] << ", ";
    }
    cout<<endl;
  }
}

//to : ツ新ツつオツつュツ津?嘉?つキツづゥツノ-ツドツ氾板債?
//id : ツδ?ツタツ氾板債?
bool check(int to, int id){
  int diff = a[to][0] - dist[id][0];

  for(int i = 1; i < to; i++){
    if(diff != a[to][i] - dist[id][i]){
      return false;
    }
  }

  return true;
}

//A : ツ新ツつオツつュツ津?嘉?つキツづゥツノ-ツドツ氾板債?
//B : Aツづーツづつづ按つーツづゥツδ?ツタツ氾板債?
//return : ツノ-ツドAツづ個づ?づ?づ?づ?凝淞つュツづ可つュツづ?づつつ「ツづ?づゥツδ?ツタツ氾板債?
int connectAB(int A, int B){
  int d = a[A][0] - dist[B][0];

  if(d == 1){
    cnt[B]++;
    return B;
  }

  for(int i = 0; i < d - 1; i++){
    if(i == 0){
      t[B].push_back(m);
      t[m].push_back(B);
      cnt[m]++;
      cnt[B]++;
    }
    else{
      t[m].push_back(m - 1);
      t[m - 1].push_back(m);
      cnt[m]++;
      cnt[m - 1]++;
    }
    m++;
  }
  cnt[m - 1]++;

  return m - 1;
}

//A : ツ新ツつオツつュツ津?嘉?つキツづゥツノ-ツドツ氾板債?
//dist[id][A]ツづ営ostツ渉堕つォツ債楪づ?
void dfs(int A, int id, int cost){
  dist[id][A] = cost;
  used[id] = true;

  for(int i = 0; i < t[id].size(); i++){
    int to = t[id][i];
    if(!used[to]){
      dfs(A, to, cost + 1);
    }
  }
}

void solve(){
  for(int i = 2; i < n; i++){
    int connect = -1;

    for(int j = 0; j < m; j++){
      if(check(i, j)){
        connect = j;
        break;
      }
    }

    //cout<<"connect : " << connect<<endl;

    near[i] = connectAB(i, connect);
    for(int j = 0; j <= i; j++){
      memset(used, 0, sizeof(used));
      dfs(j, near[j], 1);
    }
  }

  vector<int> ans;
  for(int i = 0; i < m; i++){
    ans.push_back(cnt[i]);
  }
  sort(ans.begin(), ans.end());

  for(int i = 0; i < m; i++){
    if(i != 0) cout << " ";
    cout << ans[i];
  }
  cout<<endl;
}

int validate_dfs(int from, int to, int cost){
  used[from] = true;
  if(from == to){
    return cost;
  }

  for(int i = 0; i < t[from].size(); i++){
    int TO = t[from][i];
    if(!used[TO]){
      int tmp = validate_dfs(TO, to, cost + 1);
      if(tmp != -1) return tmp;
    }
  }

  return -1;
}

bool validate(){
  for(int i = 0; i < n; i++){
    for(int j = 0; j < i; j++){
      if(near[i] == -1 || near[j] == -1) return false;
      memset(used,0,sizeof(used));
      //printf("%d(%d) --> %d(%d)\n", near[i], i,near[j], j);
      if(validate_dfs(near[i], near[j], 2) != a[i][j]){
        return false;
      }
    }
  }

  return true;
}

int main(){
  while(cin >> n, n){
    for(int i = 0; i < n; i++){
      for(int j = 0; j < n; j++){
        cin >> a[i][j];
      }
    }

    init();
    solve();

    //cout << (validate() ? "yes" : "no") << endl;
    //show();
  }
}
accuracy: 1
time_ms: 20
memory_kb: 4864
final_rank: 5