Problem:
Problem L: WW
Problem
19XX年、nつの国で連合国軍が結成された。連合国軍に属する各国では、敵軍の侵略から自国を守るために国内に１つ以上の拠点を作り、周囲を警戒している。図１は連合国の例を示し、長方形が各国を、その中にある円がその国の拠点を表す。
図1
敵軍が侵略してきた場合、それを一番最初に発見した拠点からその情報を連合国軍に属する他国または自国の拠点に発信することになっている。
情報を他の拠点に伝えるには正の整数のコストがかかる。
また、各国では自国の拠点のうち、連合国軍翻訳通信部(ATIS : Allied Translator and Interpreter Section)に属する兵士が配属されている拠点をちょうど１つだけ持っている。
この兵士だけが連合国軍に属する全ての国の言語を話すことができ、その他の兵士は自分の国の言語しか話せない。
その為、情報を受け取った拠点が他国に情報を伝えようとした際にその拠点がATISに属する兵士をもたない場合、そこから自国のATISに属する兵士をもつ拠点に情報を伝え他国に情報を発信してもらう必要がある。
国毎で各拠点に０から順に[その国がもつ拠点の数-1]までの番号が割り振られており、０番目の拠点にATISに属する兵士がいる。
つまり、他国の拠点に情報を伝達できるのは０番目の拠点だけであり、その他の拠点から他国へは通信できない。
また、その国の０番目の拠点に情報が伝わればその国全体に情報が伝わったものとする。
様々な理由から、全ての拠点の間で通信ができるとは限らない。
ある拠点から別の拠点に情報を伝える事ができたとしても、その逆が成り立つとは限らない。
また、ある拠点から別の拠点に情報を伝えた際のコストとその逆でかかるコストが同じとも限らない。
これらのことを踏まえて、ある拠点が敵軍を発見した際に、連合国軍全体に情報が行き渡るコストの総和が最も少ない伝達方法を知りたい。
連合国軍に属する全ての国の０番目の拠点に対して最初に敵軍を見つけた拠点から情報が伝達された時、連合国軍全体に情報が行き渡ったものとする。
敵軍を発見した拠点が質問として与えられるので、最も少ないコストでその情報が連合国軍全体に行き渡る伝達方法とそのコストを出力せよ。
例えば、以下のケースについて考える ( Sample Input 4、１つめの質問 )
国neepalの1番目の拠点が敵軍を発見したとする。
この場合、１番目の拠点から他国へは通信できないため、まず自国の０番目の拠点へ情報を伝える。
次に、０番目の拠点から国luxenbourg,nowayに情報を伝える。
neepalからluxenbourgの０番目の拠点へ直接通信することはできるが、３番目の拠点に情報を伝え、そこから０番目の拠点へ伝えたほうがコストが少なく済む。
この場合、全ての国の０番目の国へ情報を伝えるためにかかる最小のコストは１２となる。
コストが１２で済む伝達方法は複数存在するが、そのうちのどれか一つを答えとして出力すれば良い。
以下の図２の赤い矢印はその答えのうちの１つである。
図2
Input
n
countryname
0
m
0
countryname
1
m
1
…
countryname
n-1
m
n-1
e
c1
0
v1
0
c2
0
v2
0
cost
0
c1
1
v1
1
c2
1
v2
1
cost
1
…
c1
e-1
v1
e-1
c2
e-1
v2
e-1
cost
e-1
q
c3
0
v3
0
c3
1
v3
1
…
c3
q-1
v3
q-1
n
は連合国軍に属する国の数を表す
countryname
i
は連合国軍に属する
i
番目の国名を,
m
i
は
i
番目の国の拠点の数を表す
e
は通信可能な拠点のペアの数を表す
続く
e
行には国
c1
i
の拠点
v1
i
から国
c2
i
の拠点
v2
i
に情報を伝えるのにかかるコスト
cost
i
が与えられる
q
は質問の数を表す
続く
q
行には敵軍を発見した国の名前
c3
i
とその拠点
v3
i
が与えられる
c1
i
,
c2
i
,
c3
i
は連合国軍に属する国のいずれかである
v1
i
,
v2
i
,
v3
i
はその国の拠点の数以上である事は無い
Constraints
1 ≤
n
≤ 26
1 ≤
m
i
≤ 100
0 ≤
e
≤ 322400
0 ≤
cost
i
≤ 100
1 ≤
q
≤ 10
countryname
は小文字のアルファベット ‘a’ から’z’までで構成される長さ１以上２０以下の文字列である
同じ名前の国が2つ以上与えられる事はない
通信可能な拠点のペアの
c1
i
と
c2
i
が同じ時、
v1
i
と
v2
i
は異なる
通信可能な拠点のペアの
c1
i
と
c2
i
が異なる時、
v1
i
は必ず0である
Output
各質問に対して以下の形式で答えを出力する。
各質問に対する答えの最後の行には、５つの '-’ からなる"-----” ( “ は除く ) という1行を出力すること。
答えが存在する場合
1行目に質問で与えられた国の拠点から連合国軍全体に情報が行き渡るために必要なコストの最小値を出力する。
2行目以降にはその時の伝達方法を出力する。
伝達方法は以下の形式で表現される。
c4
0
v4
0
c5
0
v5
0
c4
1
v4
1
c5
1
v5
1
...
国
c4
i
の拠点
v4
i
から国
c5
i
の拠点
v5
i
に情報を伝えたことを表す。
以下の事に気をつける事。
通信が行われた順番通りに出力する必要はない
コストの総和が最小となる伝達方法が1つ以上存在する場合、そのうちのいずれか１つを出力すれば良い
同じ通信可能なペアを２回以上出力してはいけない
c4
i
,
c5
i
は入力で与えられた国のいずれかでなければならない
v4
i
,
v5
i
はその国の拠点の数未満でなければならない
答えが存在しない場合
1行に ”Impossible” ( “ は除く ) と出力すること。
Sample Input 1
3
frence 1
usi 1
powland 1
2
usi 0 frence 0 10
frence 0 powland 0 10
2
usi 0
powland 0
Sample Output 1
20
usi 0 frence 0
frence 0 powland 0
-----
Impossible
-----
Sample Input 2
2
usso 2
caneda 2
4
usso 1 usso 0 1
usso 0 caneda 0 10
usso 0 caneda 1 2
caneda 1 caneda 0 2
1
usso 1
Sample Output 2
5
usso 1 usso 0
usso 0 caneda 1
caneda 1 caneda 0
-----
Sample Input 3
3
chinax 1
ok 1
austraria 2
6
chinax 0 austra
...(truncated)

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
using namespace std;
typedef long long  ll;
typedef pair<int, int > pii;


typedef vector<vector<int> > matrix;

struct Node {
  vector<Node> vs;
  vector<pii> con;              // (src,to)
  int v;
  void print() {
    if (vs.size() == 0) {
      cout << v;
    } else {
      REP(i,vs.size()) {
        cout << "[";
        vs[i].print();
        cout << "]";
        cout << "(" << con[i].first << "," << con[i].second <<")";
      }
    }
  }
  bool exist(int a) {
    if (vs.size() == 0) {
      return (v == a);
    } else {
      REP(i,vs.size()) {
        if (vs[i].exist(a)) return 1;
      }
    }
    return 0;
  }
  bool connect(vector<pii> &res, int a) {
    // print();cout << endl;
    // cout << a << endl;
    // cout << ":" << exist(a) << endl;
    bool f = 0;
    if (vs.size() == 0) {
      f = v == a;
    } else {
      REP(i,vs.size()) {
        int ii = (i+1)%vs.size();
        if (vs[ii].exist(a)) {
          vs[ii].connect(res,a);
        } else {
          res.push_back(con[i]);
          vs[ii].connect(res,con[i].second);
        }
      }
    }
    return f;
  }
};

typedef vector<vector<int> > matrix;
const int inf = 1<<29;
  
void backward_traverse(int v, int s, int r, matrix &g,
                       vector<int> &no, vector< vector<int> > &comp,
                       vector<int> &prev, vector<int> &mcost,
                       vector<Node> &nodes, vector<pii> &edge,
                       vector<int> &mark, int &cost, bool &found) {
  const int n = g.size();
  if (mark[v]) {
    vector<int> temp = no;
    found = true;
    Node node;
    do {
      cost += mcost[v];
      node.con.push_back(edge[v]);
      v = prev[v];
      node.vs.push_back(nodes[v]);
      
      if (v != s) {
        while (comp[v].size() > 0) {
          no[comp[v].back()] = s;
          comp[s].push_back(comp[v].back());
          comp[v].pop_back();
        }
      }
    } while (v != s);
    reverse(ALL(node.vs));
    reverse(ALL(node.con));
    nodes[s] = node;
    for (int j = 0; j < n; ++j)
      if (j != r && no[j] == s)
        for (int i = 0; i < n; ++i)
          if (no[i] != s && g[i][j] < inf) {
            g[i][j] -= mcost[ temp[j] ];
          }
  }
  mark[v] = true;
  for (int i = 0; i < n; ++i)
    if (no[i] != no[v] && prev[ no[i] ] == v)
      if (!mark[ no[i] ] || i == s)
        backward_traverse(i, s, r, g,
                          no, comp, prev, mcost, nodes, edge, mark, cost, found);
}

int minimum_spanning_arborescence(int r, matrix g, vector<pii> &edges) {
  const int n = g.size();
  vector<int> no(n);
  vector< vector<int> > comp(n);
  vector<Node> nodes(n);
  for (int i = 0; i < n; ++i) {
    no[i] = i;
    comp[i].push_back(i);
    nodes[i].v = i;
  }
  int cost = 0;
  vector<int> pprev;
  while (1) {
    vector<int> prev(n, -1);
    vector<int> mcost(n, inf);
    vector<pii> edge(n);
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        if (j == r) continue;
        if (no[i] != no[j] && g[i][j] < inf) {
          if (g[i][j] < mcost[ no[j] ]) {
            mcost[ no[j] ] = g[i][j];
            prev[ no[j] ] = no[i];
            edge[no[j]] = pii(i,j);
          }
        }
      }
    }
    pprev = prev;
    bool stop = true;
    vector<int> mark(n);
    for (int i = 0; i < n; ++i) {
      if (i == r || mark[i] || comp[i].size() == 0) continue;
      bool found = false;
      backward_traverse(i, i, r, g,
                        no, comp, prev, mcost, nodes, edge, mark, cost, found);
      if (found) stop = false;
    }
    // cout << "cost " << cost << endl;
    // REP(i,n) {
    //   REP(j,n) {
    //     cout << g[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    // cout << "no: ";
    // FOR(it, no) cout << *it << " " ; cout << endl;
    // cout << "mcost: ";
    // FOR(it, mcost) cout << *it << " " ; cout << endl;
    
    // cout << "prev: ";
    // REP(i,n) cout << prev[i] << " "; cout << endl;
    // cout << "prevprev: ";
    // FOR(it, prevprev) cout << *it << " "; cout << endl;
    // cout << endl;
    // nodes[1].print(); cout << endl;
    if (stop) {
      int cnt = 0;
      REP(i,n) {
        if (prev[i] >= 0) {
          nodes[i].connect(edges, edge[i].second);
          // nodes[i].print();
          // cout << " " << edge[i].first << " " << edge[i].second <<endl;
          edges.push_back(pii(edge[i].first, edge[i].second));
          cost += mcost[i];
        }
        if (prev[no[i]] < 0) cnt++;
      }
      // FOR(it, edges) {
      //   cout << it->first << " " << it->second << endl;
      // }
      if (cnt != 1) return -1;
      return cost;
    }
  }
}

struct Edge {
  int src, dst;
  int weight;
  Edge(int src, int dst, int weight) :
    src(src),dst(dst),weight(weight) {}
  bool operator<(const Edge &rhs) const {
    return weight > rhs.weight;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

vector<int> dijkstra(const Graph &g, int s, vector<int> &prev) {
  int n = g.size();
  vector<int> dist(n,inf);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (prev[e.dst] != -1) continue;
    prev[e.dst] = e.src;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}

vector<int> buildPath(const vector<int> &prev, int t) {
  vector<int> path;
  for (int u = t; u >= 0; u = prev[u])
    path.push_back(u);
  reverse(ALL(path));
  return path;
}

string name[100];
int m[100];
int sum[100];
pii p[100000];

vector<int> dprev[100];

string tostr(pii a) {
  stringstream ss;
  ss << name[a.first] << " " << a.second;
  return ss.str();
}

int main() {
  int n;
  while(cin >> n) {
    sum[0] = 0;
    int N = 0;
    map<string, int > mp;
    for (int i=0; i<n; ++i) {
      cin >>name[i] >> m[i];
      sum[i+1] = sum[i] + m[i];
      mp[name[i]] = i;
      N += m[i];
    }
    int cnt = 0;
    for (int i=0; i<n; ++i) {
      for (int j=0; j<m[i]; ++j) {
        p[cnt++] = pii(i,j);
      }
    }
    int E;
    cin >> E;
    Graph g(N);
    for(int i=0; i<E; ++i) {
      string cs1,cs2;
      int v1,v2,c;
      cin >> cs1>>v1>>cs2>>v2>>c;
      int c1 = mp[cs1];
      int c2 = mp[cs2];
      int a = sum[c1] + v1;
      int b = sum[c2] + v2;
      g[a].push_back(Edge(a,b,c));
    }
    matrix mat(n,vector<int>(n));
    vector<int> prev;
    for (int i=0; i<n ;++i) {
      vector<int> dist = dijkstra(g, sum[i], dprev[i]);
      // FOR(it, dprev[i]) cout << "*" << *it; cout << endl;
      for (int j=0; j<n; ++j) {
        mat[i][j] = dist[sum[j]];
      }
    }
    // for (int i=0; i<n; ++i) {
    //   for (int j=0;j<n; ++j) {
    //     cout << mat[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    int Q;
    cin >> Q;
    for (int i=0; i<Q; ++i) {
      string cs3;
      int v3;
      cin >> cs3 >> v3;
      int c3 = mp[cs3];
      int a = sum[c3] + v3;
      vector<int> dist = dijkstra(g, a, prev);
      bool ng = 0;
      REP(i,n) {
        if (dist[sum[i]] == inf) {
          ng = 1;
        }
      }
      if (ng) {
        cout << "Impossible" << endl;
      } else {
        int res = dist[sum[c3]];
        vector<pii> edges;
        int tmpres = minimum_spanning_arborescence(c3, mat, edges);
        int ans = res + tmpres;

        if (res == inf || tmpres < 0)  {
          assert(0);
        } else {
          cout << ans << endl;
          vector<int> path = buildPath(prev, sum[c3]);
          set<pii> ST; int cnt = 0;
          REP(i,path.size()-1) {
            ST.insert(pii(path[i], path[i+1])); cnt++;
            // cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
          }
          assert(edges.size() == n-1);
          set<int> S;
          FOR(it, edges) S.insert(it->second);
          assert(S.size() == n-1);
          FOR(it, edges) {
            int a = it->second;
            int b = it->first;
            int A = sum[a];

            vector<int> path = buildPath(dprev[b], A);
            REP(i,path.size()-1) {
              ST.insert(pii(path[i], path[i+1])); cnt++;
              // cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
            }
          }
          FOR(it, ST) {
            cout << tostr(p[it->first]) << " " << tostr(p[it->second]) << endl;
          }
        }
      }
      puts("-----");
    }
  }
}
accuracy: 1
time_ms: 340
memory_kb: 7596
final_rank: 2

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
using namespace std;
typedef long long  ll;
typedef pair<int, int > pii;


typedef vector<vector<int> > matrix;

struct Node {
  vector<Node> vs;
  vector<pii> con;              // (src,to)
  int v;
  void print() {
    if (vs.size() == 0) {
      cout << v;
    } else {
      REP(i,vs.size()) {
        cout << "[";
        vs[i].print();
        cout << "]";
        cout << "(" << con[i].first << "," << con[i].second <<")";
      }
    }
  }
  bool exist(int a) {
    if (vs.size() == 0) {
      return (v == a);
    } else {
      REP(i,vs.size()) {
        if (vs[i].exist(a)) return 1;
      }
    }
    return 0;
  }
  bool connect(vector<pii> &res, int a) {
    // print();cout << endl;
    // cout << a << endl;
    // cout << ":" << exist(a) << endl;
    bool f = 0;
    if (vs.size() == 0) {
      f = v == a;
    } else {
      REP(i,vs.size()) {
        int ii = (i+1)%vs.size();
        if (vs[ii].exist(a)) {
          vs[ii].connect(res,a);
        } else {
          res.push_back(con[i]);
          vs[ii].connect(res,con[i].second);
        }
      }
    }
    return f;
  }
};

typedef vector<vector<int> > matrix;
const int inf = 1<<29;
  
void backward_traverse(int v, int s, int r, matrix &g,
                       vector<int> &no, vector< vector<int> > &comp,
                       vector<int> &prev, vector<int> &mcost,
                       vector<Node> &nodes, vector<pii> &edge,
                       vector<int> &mark, int &cost, bool &found) {
  const int n = g.size();
  if (mark[v]) {
    vector<int> temp = no;
    found = true;
    Node node;
    do {
      cost += mcost[v];
      node.con.push_back(edge[v]);
      v = prev[v];
      node.vs.push_back(nodes[v]);
      
      if (v != s) {
        while (comp[v].size() > 0) {
          no[comp[v].back()] = s;
          comp[s].push_back(comp[v].back());
          comp[v].pop_back();
        }
      }
    } while (v != s);
    reverse(ALL(node.vs));
    reverse(ALL(node.con));
    nodes[s] = node;
    for (int j = 0; j < n; ++j)
      if (j != r && no[j] == s)
        for (int i = 0; i < n; ++i)
          if (no[i] != s && g[i][j] < inf) {
            g[i][j] -= mcost[ temp[j] ];
          }
  }
  mark[v] = true;
  for (int i = 0; i < n; ++i)
    if (no[i] != no[v] && prev[ no[i] ] == v)
      if (!mark[ no[i] ] || i == s)
        backward_traverse(i, s, r, g,
                          no, comp, prev, mcost, nodes, edge, mark, cost, found);
}

int minimum_spanning_arborescence(int r, matrix g, vector<pii> &edges) {
  const int n = g.size();
  vector<int> no(n);
  vector< vector<int> > comp(n);
  vector<Node> nodes(n);
  for (int i = 0; i < n; ++i) {
    no[i] = i;
    comp[i].push_back(i);
    nodes[i].v = i;
  }
  int cost = 0;
  vector<int> pprev;
  while (1) {
    vector<int> prev(n, -1);
    vector<int> mcost(n, inf);
    vector<pii> edge(n);
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        if (j == r) continue;
        if (no[i] != no[j] && g[i][j] < inf) {
          if (g[i][j] < mcost[ no[j] ]) {
            mcost[ no[j] ] = g[i][j];
            prev[ no[j] ] = no[i];
            edge[no[j]] = pii(i,j);
          }
        }
      }
    }
    pprev = prev;
    bool stop = true;
    vector<int> mark(n);
    for (int i = 0; i < n; ++i) {
      if (i == r || mark[i] || comp[i].size() == 0) continue;
      bool found = false;
      backward_traverse(i, i, r, g,
                        no, comp, prev, mcost, nodes, edge, mark, cost, found);
      if (found) stop = false;
    }
    // cout << "cost " << cost << endl;
    // REP(i,n) {
    //   REP(j,n) {
    //     cout << g[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    // cout << "no: ";
    // FOR(it, no) cout << *it << " " ; cout << endl;
    // cout << "mcost: ";
    // FOR(it, mcost) cout << *it << " " ; cout << endl;
    
    // cout << "prev: ";
    // REP(i,n) cout << prev[i] << " "; cout << endl;
    // cout << "prevprev: ";
    // FOR(it, prevprev) cout << *it << " "; cout << endl;
    // cout << endl;
    // nodes[1].print(); cout << endl;
    if (stop) {
      int cnt = 0;
      REP(i,n) {
        if (prev[i] >= 0) {
          nodes[i].connect(edges, edge[i].second);
          // nodes[i].print();
          // cout << " " << edge[i].first << " " << edge[i].second <<endl;
          edges.push_back(pii(edge[i].first, edge[i].second));
          cost += mcost[i];
        }
        if (prev[no[i]] < 0) cnt++;
      }
      // FOR(it, edges) {
      //   cout << it->first << " " << it->second << endl;
      // }
      if (cnt != 1) return -1;
      return cost;
    }
  }
}

struct Edge {
  int src, dst;
  int weight;
  Edge(int src, int dst, int weight) :
    src(src),dst(dst),weight(weight) {}
  bool operator<(const Edge &rhs) const {
    return weight > rhs.weight;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

vector<int> dijkstra(const Graph &g, int s, vector<int> &prev) {
  int n = g.size();
  vector<int> dist(n,inf);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (prev[e.dst] != -1) continue;
    prev[e.dst] = e.src;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}

vector<int> buildPath(const vector<int> &prev, int t) {
  vector<int> path;
  for (int u = t; u >= 0; u = prev[u])
    path.push_back(u);
  reverse(ALL(path));
  return path;
}

string name[100];
int m[100];
int sum[100];
pii p[100000];

vector<int> dprev[100];

string tostr(pii a) {
  stringstream ss;
  ss << name[a.first] << " " << a.second;
  return ss.str();
}

int main() {
  int n;
  while(cin >> n) {
    sum[0] = 0;
    int N = 0;
    map<string, int > mp;
    for (int i=0; i<n; ++i) {
      cin >>name[i] >> m[i];
      sum[i+1] = sum[i] + m[i];
      mp[name[i]] = i;
      N += m[i];
    }
    int cnt = 0;
    for (int i=0; i<n; ++i) {
      for (int j=0; j<m[i]; ++j) {
        p[cnt++] = pii(i,j);
      }
    }
    int E;
    cin >> E;
    Graph g(N);
    for(int i=0; i<E; ++i) {
      string cs1,cs2;
      int v1,v2,c;
      cin >> cs1>>v1>>cs2>>v2>>c;
      int c1 = mp[cs1];
      int c2 = mp[cs2];
      int a = sum[c1] + v1;
      int b = sum[c2] + v2;
      g[a].push_back(Edge(a,b,c));
    }
    matrix mat(n,vector<int>(n));
    vector<int> prev;
    for (int i=0; i<n ;++i) {
      vector<int> dist = dijkstra(g, sum[i], dprev[i]);
      // FOR(it, dprev[i]) cout << "*" << *it; cout << endl;
      for (int j=0; j<n; ++j) {
        mat[i][j] = dist[sum[j]];
      }
    }
    // for (int i=0; i<n; ++i) {
    //   for (int j=0;j<n; ++j) {
    //     cout << mat[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    int Q;
    cin >> Q;
    for (int i=0; i<Q; ++i) {
      string cs3;
      int v3;
      cin >> cs3 >> v3;
      int c3 = mp[cs3];
      int a = sum[c3] + v3;
      vector<int> dist = dijkstra(g, a, prev);
      bool ng = 0;
      REP(i,n) {
        if (dist[sum[i]] == inf) {
          ng = 1;
        }
      }
      if (ng) {
        cout << "Impossible" << endl;
      } else {
        int res = dist[sum[c3]];
        vector<pii> edges;
        int tmpres = minimum_spanning_arborescence(c3, mat, edges);
        int ans = res + tmpres;

        if (res == inf || tmpres < 0)  {
          assert(0);
        } else {
          cout << ans << endl;
          vector<int> path = buildPath(prev, sum[c3]);
          set<pii> ST; int cnt = 0;
          REP(i,path.size()-1) {
            ST.insert(pii(path[i], path[i+1])); cnt++;
            cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
          }
          assert(edges.size() == n-1);
          set<int> S;
          FOR(it, edges) S.insert(it->second);
          assert(S.size() == n-1);
          FOR(it, edges) {
            int a = it->second;
            int b = it->first;
            int A = sum[a];

            vector<int> path = buildPath(dprev[b], A);
            REP(i,path.size()-1) {
              ST.insert(pii(path[i], path[i+1])); cnt++;
              cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
            }
          }
          assert(ST.size() == cnt);
        }
      }
      puts("-----");
    }
  }
}
accuracy: 0.4222222222222222
time_ms: 150
memory_kb: 4788
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
using namespace std;
typedef long long  ll;
typedef pair<int, int > pii;


typedef vector<vector<int> > matrix;

struct Node {
  vector<Node> vs;
  vector<pii> con;              // (src,to)
  int v;
  void print() {
    if (vs.size() == 0) {
      cout << v;
    } else {
      REP(i,vs.size()) {
        cout << "[";
        vs[i].print();
        cout << "]";
        cout << "(" << con[i].first << "," << con[i].second <<")";
      }
    }
  }
  bool exist(int a) {
    if (vs.size() == 0) {
      return (v == a);
    } else {
      REP(i,vs.size()) {
        if (vs[i].exist(a)) return 1;
      }
    }
    return 0;
  }
  bool connect(vector<pii> &res, int a) {
    // print();cout << endl;
    // cout << a << endl;
    // cout << ":" << exist(a) << endl;
    bool f = 0;
    if (vs.size() == 0) {
      f = v == a;
    } else {
      REP(i,vs.size()) {
        int ii = (i+1)%vs.size();
        if (vs[ii].exist(a)) {
          vs[ii].connect(res,a);
        } else {
          res.push_back(con[i]);
          vs[ii].connect(res,con[i].second);
        }
      }
    }
    return f;
  }
};

typedef vector<vector<int> > matrix;
const int inf = 1<<29;
  
void backward_traverse(int v, int s, int r, matrix &g,
                       vector<int> &no, vector< vector<int> > &comp,
                       vector<int> &prev, vector<int> &mcost,
                       vector<Node> &nodes, vector<pii> &edge,
                       vector<int> &mark, int &cost, bool &found) {
  const int n = g.size();
  if (mark[v]) {
    vector<int> temp = no;
    found = true;
    Node node;
    do {
      cost += mcost[v];
      node.con.push_back(edge[v]);
      v = prev[v];
      node.vs.push_back(nodes[v]);
      
      if (v != s) {
        while (comp[v].size() > 0) {
          no[comp[v].back()] = s;
          comp[s].push_back(comp[v].back());
          comp[v].pop_back();
        }
      }
    } while (v != s);
    reverse(ALL(node.vs));
    reverse(ALL(node.con));
    nodes[s] = node;
    for (int j = 0; j < n; ++j)
      if (j != r && no[j] == s)
        for (int i = 0; i < n; ++i)
          if (no[i] != s && g[i][j] < inf) {
            g[i][j] -= mcost[ temp[j] ];
          }
  }
  mark[v] = true;
  for (int i = 0; i < n; ++i)
    if (no[i] != no[v] && prev[ no[i] ] == v)
      if (!mark[ no[i] ] || i == s)
        backward_traverse(i, s, r, g,
                          no, comp, prev, mcost, nodes, edge, mark, cost, found);
}

int minimum_spanning_arborescence(int r, matrix g, vector<pii> &edges) {
  const int n = g.size();
  vector<int> no(n);
  vector< vector<int> > comp(n);
  vector<Node> nodes(n);
  for (int i = 0; i < n; ++i) {
    no[i] = i;
    comp[i].push_back(i);
    nodes[i].v = i;
  }
  int cost = 0;
  vector<int> pprev;
  while (1) {
    vector<int> prev(n, -1);
    vector<int> mcost(n, inf);
    vector<pii> edge(n);
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        if (j == r) continue;
        if (no[i] != no[j] && g[i][j] < inf) {
          if (g[i][j] < mcost[ no[j] ]) {
            mcost[ no[j] ] = g[i][j];
            prev[ no[j] ] = no[i];
            edge[no[j]] = pii(i,j);
          }
        }
      }
    }
    pprev = prev;
    bool stop = true;
    vector<int> mark(n);
    for (int i = 0; i < n; ++i) {
      if (i == r || mark[i] || comp[i].size() == 0) continue;
      bool found = false;
      backward_traverse(i, i, r, g,
                        no, comp, prev, mcost, nodes, edge, mark, cost, found);
      if (found) stop = false;
    }
    // cout << "cost " << cost << endl;
    // REP(i,n) {
    //   REP(j,n) {
    //     cout << g[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    // cout << "no: ";
    // FOR(it, no) cout << *it << " " ; cout << endl;
    // cout << "mcost: ";
    // FOR(it, mcost) cout << *it << " " ; cout << endl;
    
    // cout << "prev: ";
    // REP(i,n) cout << prev[i] << " "; cout << endl;
    // cout << "prevprev: ";
    // FOR(it, prevprev) cout << *it << " "; cout << endl;
    // cout << endl;
    // nodes[1].print(); cout << endl;
    if (stop) {
      int cnt = 0;
      REP(i,n) {
        if (prev[i] >= 0) {
          nodes[i].connect(edges, edge[i].second);
          // nodes[i].print();
          // cout << " " << edge[i].first << " " << edge[i].second <<endl;
          edges.push_back(pii(edge[i].first, edge[i].second));
          cost += mcost[i];
        }
        if (prev[no[i]] < 0) cnt++;
      }
      // FOR(it, edges) {
      //   cout << it->first << " " << it->second << endl;
      // }
      if (cnt != 1) return -1;
      return cost;
    }
  }
}

struct Edge {
  int src, dst;
  int weight;
  Edge(int src, int dst, int weight) :
    src(src),dst(dst),weight(weight) {}
  bool operator<(const Edge &rhs) const {
    return weight > rhs.weight;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

vector<int> dijkstra(const Graph &g, int s, vector<int> &prev) {
  int n = g.size();
  vector<int> dist(n,inf);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (prev[e.dst] != -1) continue;
    prev[e.dst] = e.src;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}

vector<int> buildPath(const vector<int> &prev, int t) {
  vector<int> path;
  for (int u = t; u >= 0; u = prev[u])
    path.push_back(u);
  reverse(ALL(path));
  return path;
}

string name[100];
int m[100];
int sum[100];
pii p[100000];

vector<int> dprev[100];

string tostr(pii a) {
  stringstream ss;
  ss << name[a.first] << " " << a.second;
  return ss.str();
}

int main() {
  int n;
  while(cin >> n) {
    sum[0] = 0;
    int N = 0;
    map<string, int > mp;
    for (int i=0; i<n; ++i) {
      cin >>name[i] >> m[i];
      sum[i+1] = sum[i] + m[i];
      mp[name[i]] = i;
      N += m[i];
    }
    int cnt = 0;
    for (int i=0; i<n; ++i) {
      for (int j=0; j<m[i]; ++j) {
        p[cnt++] = pii(i,j);
      }
    }
    int E;
    cin >> E;
    Graph g(N);
    for(int i=0; i<E; ++i) {
      string cs1,cs2;
      int v1,v2,c;
      cin >> cs1>>v1>>cs2>>v2>>c;
      int c1 = mp[cs1];
      int c2 = mp[cs2];
      int a = sum[c1] + v1;
      int b = sum[c2] + v2;
      g[a].push_back(Edge(a,b,c));
    }
    matrix mat(n,vector<int>(n));
    vector<int> prev;
    for (int i=0; i<n ;++i) {
      vector<int> dist = dijkstra(g, sum[i], dprev[i]);
      // FOR(it, dprev[i]) cout << "*" << *it; cout << endl;
      for (int j=0; j<n; ++j) {
        mat[i][j] = dist[sum[j]];
      }
    }
    // for (int i=0; i<n; ++i) {
    //   for (int j=0;j<n; ++j) {
    //     cout << mat[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    int Q;
    cin >> Q;
    for (int i=0; i<Q; ++i) {
      string cs3;
      int v3;
      cin >> cs3 >> v3;
      int c3 = mp[cs3];
      int a = sum[c3] + v3;
      vector<int> dist = dijkstra(g, a, prev);
      bool ng = 0;
      REP(i,n) {
        if (dist[sum[i]] == inf) {
          ng = 1;
        }
      }
      if (ng) {
        cout << "Impossible" << endl;
      } else {
        int res = dist[sum[c3]];
        vector<pii> edges;
        int tmpres = minimum_spanning_arborescence(c3, mat, edges);
        int ans = res + tmpres;

        if (res == inf || tmpres < 0)  {
          assert(0);
        } else {
          cout << ans << endl;
          vector<int> path = buildPath(prev, sum[c3]);
          REP(i,path.size()-1) {
            cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
          }
          assert(edges.size() == n-1);
          set<int> S;
          FOR(it, edges) S.insert(it->second);
          assert(S.size() == n-1);
          FOR(it, edges) {
            int a = it->second;
            int b = it->first;
            int A = sum[a];

            vector<int> path = buildPath(dprev[b], A);
            REP(i,path.size()-1) {
              cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
            }
          }
        
        }
      }
      puts("-----");
    }
  }
}
accuracy: 0.4222222222222222
time_ms: 150
memory_kb: 4788
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
using namespace std;
typedef long long  ll;
typedef pair<int, int > pii;


typedef vector<vector<int> > matrix;

struct Node {
  vector<Node> vs;
  vector<pii> con;              // (src,to)
  int v;
  void print() {
    if (vs.size() == 0) {
      cout << v;
    } else {
      REP(i,vs.size()) {
        cout << "[";
        vs[i].print();
        cout << "]";
        cout << "(" << con[i].first << "," << con[i].second <<")";
      }
    }
  }
  bool exist(int a) {
    if (vs.size() == 0) {
      return (v == a);
    } else {
      REP(i,vs.size()) {
        if (vs[i].exist(a)) return 1;
      }
    }
    return 0;
  }
  bool connect(vector<pii> &res, int a) {
    // print();cout << endl;
    // cout << a << endl;
    // cout << ":" << exist(a) << endl;
    bool f = 0;
    if (vs.size() == 0) {
      f = v == a;
    } else {
      REP(i,vs.size()) {
        int ii = (i+1)%vs.size();
        if (vs[ii].exist(a)) {
          vs[ii].connect(res,a);
        } else {
          res.push_back(con[i]);
          vs[ii].connect(res,con[i].second);
        }
      }
    }
    return f;
  }
};

typedef vector<vector<int> > matrix;
const int inf = 1<<29;
  
void backward_traverse(int v, int s, int r, matrix &g,
                       vector<int> &no, vector< vector<int> > &comp,
                       vector<int> &prev, vector<int> &mcost,
                       vector<Node> &nodes, vector<pii> &edge,
                       vector<int> &mark, int &cost, bool &found) {
  const int n = g.size();
  if (mark[v]) {
    vector<int> temp = no;
    found = true;
    Node node;
    do {
      cost += mcost[v];
      node.con.push_back(edge[v]);
      v = prev[v];
      node.vs.push_back(nodes[v]);
      
      if (v != s) {
        while (comp[v].size() > 0) {
          no[comp[v].back()] = s;
          comp[s].push_back(comp[v].back());
          comp[v].pop_back();
        }
      }
    } while (v != s);
    reverse(ALL(node.vs));
    reverse(ALL(node.con));
    nodes[s] = node;
    for (int j = 0; j < n; ++j)
      if (j != r && no[j] == s)
        for (int i = 0; i < n; ++i)
          if (no[i] != s && g[i][j] < inf) {
            g[i][j] -= mcost[ temp[j] ];
          }
  }
  mark[v] = true;
  for (int i = 0; i < n; ++i)
    if (no[i] != no[v] && prev[ no[i] ] == v)
      if (!mark[ no[i] ] || i == s)
        backward_traverse(i, s, r, g,
                          no, comp, prev, mcost, nodes, edge, mark, cost, found);
}

int minimum_spanning_arborescence(int r, matrix g, vector<pii> &edges) {
  const int n = g.size();
  vector<int> no(n);
  vector< vector<int> > comp(n);
  vector<Node> nodes(n);
  for (int i = 0; i < n; ++i) {
    no[i] = i;
    comp[i].push_back(i);
    nodes[i].v = i;
  }
  int cost = 0;
  vector<int> pprev;
  while (1) {
    vector<int> prev(n, -1);
    vector<int> mcost(n, inf);
    vector<pii> edge(n);
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        if (j == r) continue;
        if (no[i] != no[j] && g[i][j] < inf) {
          if (g[i][j] < mcost[ no[j] ]) {
            mcost[ no[j] ] = g[i][j];
            prev[ no[j] ] = no[i];
            edge[no[j]] = pii(i,j);
          }
        }
      }
    }
    pprev = prev;
    bool stop = true;
    vector<int> mark(n);
    for (int i = 0; i < n; ++i) {
      if (i == r || mark[i] || comp[i].size() == 0) continue;
      bool found = false;
      backward_traverse(i, i, r, g,
                        no, comp, prev, mcost, nodes, edge, mark, cost, found);
      if (found) stop = false;
    }
    // cout << "cost " << cost << endl;
    // REP(i,n) {
    //   REP(j,n) {
    //     cout << g[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    // cout << "no: ";
    // FOR(it, no) cout << *it << " " ; cout << endl;
    // cout << "mcost: ";
    // FOR(it, mcost) cout << *it << " " ; cout << endl;
    
    // cout << "prev: ";
    // REP(i,n) cout << prev[i] << " "; cout << endl;
    // cout << "prevprev: ";
    // FOR(it, prevprev) cout << *it << " "; cout << endl;
    // cout << endl;
    // nodes[1].print(); cout << endl;
    if (stop) {
      int cnt = 0;
      REP(i,n) {
        if (prev[i] >= 0) {
          nodes[i].connect(edges, edge[i].second);
          // nodes[i].print();
          // cout << " " << edge[i].first << " " << edge[i].second <<endl;
          edges.push_back(pii(edge[i].first, edge[i].second));
          cost += mcost[i];
        }
        if (prev[no[i]] < 0) cnt++;
      }
      // FOR(it, edges) {
      //   cout << it->first << " " << it->second << endl;
      // }
      if (cnt != 1) return -1;
      return cost;
    }
  }
}

struct Edge {
  int src, dst;
  int weight;
  Edge(int src, int dst, int weight) :
    src(src),dst(dst),weight(weight) {}
  bool operator<(const Edge &rhs) const {
    return weight > rhs.weight;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

vector<int> dijkstra(const Graph &g, int s, vector<int> &prev) {
  int n = g.size();
  vector<int> dist(n,inf);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (prev[e.dst] != -1) continue;
    prev[e.dst] = e.src;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}

vector<int> buildPath(const vector<int> &prev, int t) {
  vector<int> path;
  for (int u = t; u >= 0; u = prev[u])
    path.push_back(u);
  reverse(ALL(path));
  return path;
}

string name[100];
int m[100];
int sum[100];
pii p[100000];

vector<int> dprev[100];

string tostr(pii a) {
  stringstream ss;
  ss << name[a.first] << " " << a.second;
  return ss.str();
}

int main() {
  int n;
  while(cin >> n) {
    sum[0] = 0;
    int N = 0;
    map<string, int > mp;
    for (int i=0; i<n; ++i) {
      cin >>name[i] >> m[i];
      sum[i+1] = sum[i] + m[i];
      mp[name[i]] = i;
      N += m[i];
    }
    int cnt = 0;
    for (int i=0; i<n; ++i) {
      for (int j=0; j<m[i]; ++j) {
        p[cnt++] = pii(i,j);
      }
    }
    int E;
    cin >> E;
    Graph g(N);
    for(int i=0; i<E; ++i) {
      string cs1,cs2;
      int v1,v2,c;
      cin >> cs1>>v1>>cs2>>v2>>c;
      int c1 = mp[cs1];
      int c2 = mp[cs2];
      int a = sum[c1] + v1;
      int b = sum[c2] + v2;
      g[a].push_back(Edge(a,b,c));
    }
    matrix mat(n,vector<int>(n));
    vector<int> prev;
    for (int i=0; i<n ;++i) {
      vector<int> dist = dijkstra(g, sum[i], dprev[i]);
      // FOR(it, dprev[i]) cout << "*" << *it; cout << endl;
      for (int j=0; j<n; ++j) {
        mat[i][j] = dist[sum[j]];
      }
    }
    // for (int i=0; i<n; ++i) {
    //   for (int j=0;j<n; ++j) {
    //     cout << mat[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    int Q;
    cin >> Q;
    for (int i=0; i<Q; ++i) {
      string cs3;
      int v3;
      cin >> cs3 >> v3;
      int c3 = mp[cs3];
      int a = sum[c3] + v3;
      vector<int> dist = dijkstra(g, a, prev);
      bool ng = 0;
      REP(i,n) {
        if (dist[sum[i]] == inf) {
          ng = 1;
        }
      }
      if (ng) {
        cout << "Impossible" << endl;
      } else {
        int res = dist[sum[c3]];
        vector<pii> edges;
        int tmpres = minimum_spanning_arborescence(c3, mat, edges);
        int ans = res + tmpres;

        if (res == inf || tmpres < 0)  {
          assert(0);
        } else {
          cout << ans << endl;
          vector<int> path = buildPath(prev, sum[c3]);
          REP(i,path.size()-1) {
            cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
          }
          assert(edges.size() == n-1);
          FOR(it, edges) {
            int a = it->second;
            int b = it->first;
            int A = sum[a];

            vector<int> path = buildPath(dprev[b], A);
            REP(i,path.size()-1) {
              cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
            }
          }
        
        }
      }
      puts("-----");
    }
  }
}
accuracy: 0.4222222222222222
time_ms: 150
memory_kb: 4788
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
using namespace std;
typedef long long  ll;
typedef pair<int, int > pii;


typedef vector<vector<int> > matrix;

struct Node {
  vector<Node> vs;
  vector<pii> con;              // (src,to)
  int v;
  void print() {
    if (vs.size() == 0) {
      cout << v;
    } else {
      REP(i,vs.size()) {
        cout << "[";
        vs[i].print();
        cout << "]";
        cout << "(" << con[i].first << "," << con[i].second <<")";
      }
    }
  }
  bool exist(int a) {
    if (vs.size() == 0) {
      return (v == a);
    } else {
      REP(i,vs.size()) {
        if (vs[i].exist(a)) return 1;
      }
    }
    return 0;
  }
  bool connect(vector<pii> &res, int a) {
    // print();cout << endl;
    // cout << a << endl;
    // cout << ":" << exist(a) << endl;
    bool f = 0;
    if (vs.size() == 0) {
      f = v == a;
    } else {
      REP(i,vs.size()) {
        int ii = (i+1)%vs.size();
        if (vs[ii].exist(a)) {
          vs[ii].connect(res,a);
        } else {
          res.push_back(con[i]);
          vs[ii].connect(res,con[i].second);
        }
      }
    }
    return f;
  }
};

typedef vector<vector<int> > matrix;
const int inf = 1<<29;
  
void backward_traverse(int v, int s, int r, matrix &g,
                       vector<int> &no, vector< vector<int> > &comp,
                       vector<int> &prev, vector<int> &mcost,
                       vector<Node> &nodes, vector<pii> &edge,
                       vector<int> &mark, int &cost, bool &found) {
  const int n = g.size();
  if (mark[v]) {
    vector<int> temp = no;
    found = true;
    Node node;
    do {
      cost += mcost[v];
      node.con.push_back(edge[v]);
      v = prev[v];
      node.vs.push_back(nodes[v]);
      
      if (v != s) {
        while (comp[v].size() > 0) {
          no[comp[v].back()] = s;
          comp[s].push_back(comp[v].back());
          comp[v].pop_back();
        }
      }
    } while (v != s);
    reverse(ALL(node.vs));
    reverse(ALL(node.con));
    nodes[s] = node;
    for (int j = 0; j < n; ++j)
      if (j != r && no[j] == s)
        for (int i = 0; i < n; ++i)
          if (no[i] != s && g[i][j] < inf) {
            g[i][j] -= mcost[ temp[j] ];
          }
  }
  mark[v] = true;
  for (int i = 0; i < n; ++i)
    if (no[i] != no[v] && prev[ no[i] ] == v)
      if (!mark[ no[i] ] || i == s)
        backward_traverse(i, s, r, g,
                          no, comp, prev, mcost, nodes, edge, mark, cost, found);
}

int minimum_spanning_arborescence(int r, matrix g, vector<pii> &edges) {
  const int n = g.size();
  vector<int> no(n);
  vector< vector<int> > comp(n);
  vector<Node> nodes(n);
  for (int i = 0; i < n; ++i) {
    no[i] = i;
    comp[i].push_back(i);
    nodes[i].v = i;
  }
  int cost = 0;
  vector<int> pprev;
  while (1) {
    vector<int> prev(n, -1);
    vector<int> mcost(n, inf);
    vector<pii> edge(n);
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        if (j == r) continue;
        if (no[i] != no[j] && g[i][j] < inf) {
          if (g[i][j] < mcost[ no[j] ]) {
            mcost[ no[j] ] = g[i][j];
            prev[ no[j] ] = no[i];
            edge[no[j]] = pii(i,j);
          }
        }
      }
    }
    pprev = prev;
    bool stop = true;
    vector<int> mark(n);
    for (int i = 0; i < n; ++i) {
      if (i == r || mark[i] || comp[i].size() == 0) continue;
      bool found = false;
      backward_traverse(i, i, r, g,
                        no, comp, prev, mcost, nodes, edge, mark, cost, found);
      if (found) stop = false;
    }
    // cout << "cost " << cost << endl;
    // REP(i,n) {
    //   REP(j,n) {
    //     cout << g[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    // cout << "no: ";
    // FOR(it, no) cout << *it << " " ; cout << endl;
    // cout << "mcost: ";
    // FOR(it, mcost) cout << *it << " " ; cout << endl;
    
    // cout << "prev: ";
    // REP(i,n) cout << prev[i] << " "; cout << endl;
    // cout << "prevprev: ";
    // FOR(it, prevprev) cout << *it << " "; cout << endl;
    // cout << endl;
    // nodes[1].print(); cout << endl;
    if (stop) {
      int cnt = 0;
      REP(i,n) {
        if (prev[i] >= 0) {
          nodes[i].connect(edges, edge[i].second);
          // nodes[i].print();
          // cout << " " << edge[i].first << " " << edge[i].second <<endl;
          edges.push_back(pii(edge[i].first, edge[i].second));
          cost += mcost[i];
        }
        if (prev[no[i]] < 0) cnt++;
      }
      // FOR(it, edges) {
      //   cout << it->first << " " << it->second << endl;
      // }
      if (cnt != 1) return -1;
      return cost;
    }
  }
}

struct Edge {
  int src, dst;
  int weight;
  Edge(int src, int dst, int weight) :
    src(src),dst(dst),weight(weight) {}
  bool operator<(const Edge &rhs) const {
    return weight > rhs.weight;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

vector<int> dijkstra(const Graph &g, int s, vector<int> &prev) {
  int n = g.size();
  vector<int> dist(n,inf);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (prev[e.dst] != -1) continue;
    prev[e.dst] = e.src;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}

vector<int> buildPath(const vector<int> &prev, int t) {
  vector<int> path;
  for (int u = t; u >= 0; u = prev[u])
    path.push_back(u);
  reverse(ALL(path));
  return path;
}

string name[100];
int m[100];
int sum[100];
pii p[100000];

vector<int> dprev[100];

string tostr(pii a) {
  stringstream ss;
  ss << name[a.first] << " " << a.second;
  return ss.str();
}

int main() {
  int n;
  while(cin >> n) {
    sum[0] = 0;
    int N = 0;
    map<string, int > mp;
    for (int i=0; i<n; ++i) {
      cin >>name[i] >> m[i];
      sum[i+1] = sum[i] + m[i];
      mp[name[i]] = i;
      N += m[i];
    }
    int cnt = 0;
    for (int i=0; i<n; ++i) {
      for (int j=0; j<m[i]; ++j) {
        p[cnt++] = pii(i,j);
      }
    }
    int E;
    cin >> E;
    Graph g(N);
    for(int i=0; i<E; ++i) {
      string cs1,cs2;
      int v1,v2,c;
      cin >> cs1>>v1>>cs2>>v2>>c;
      int c1 = mp[cs1];
      int c2 = mp[cs2];
      int a = sum[c1] + v1;
      int b = sum[c2] + v2;
      g[a].push_back(Edge(a,b,c));
    }
    matrix mat(n,vector<int>(n));
    vector<int> prev;
    for (int i=0; i<n ;++i) {
      vector<int> dist = dijkstra(g, sum[i], dprev[i]);
      // FOR(it, dprev[i]) cout << "*" << *it; cout << endl;
      for (int j=0; j<n; ++j) {
        mat[i][j] = dist[sum[j]];
      }
    }
    // for (int i=0; i<n; ++i) {
    //   for (int j=0;j<n; ++j) {
    //     cout << mat[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    int Q;
    cin >> Q;
    for (int i=0; i<Q; ++i) {
      string cs3;
      int v3;
      cin >> cs3 >> v3;
      int c3 = mp[cs3];
      int a = sum[c3] + v3;
      vector<int> dist = dijkstra(g, a, prev);
      bool ng = 0;
      REP(i,n) {
        if (dist[sum[i]] == inf) {
          ng = 1;
        }
      }
      if (ng) {
        cout << "Impossible" << endl;
      } else {
        int res = dist[sum[c3]];
        vector<pii> edges;
        int tmpres = minimum_spanning_arborescence(c3, mat, edges);
        int ans = res + tmpres;

        if (res == inf || tmpres < 0)  {
          assert(0);
        } else {
          cout << ans << endl;
          vector<int> path = buildPath(prev, sum[c3]);
          REP(i,path.size()-1) {
            cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
          }
          FOR(it, edges) {
            int a = it->second;
            int b = it->first;
            int A = sum[a];

            vector<int> path = buildPath(dprev[b], A);
            REP(i,path.size()-1) {
              cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
            }
          }
        
        }
      }
      puts("-----");
    }
  }
}
accuracy: 0.4222222222222222
time_ms: 150
memory_kb: 4788
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
using namespace std;
typedef long long  ll;
typedef pair<int, int > pii;


typedef vector<vector<int> > matrix;

struct Node {
  vector<Node> vs;
  vector<pii> con;              // (src,to)
  int v;
  void print() {
    if (vs.size() == 0) {
      cout << v;
    } else {
      REP(i,vs.size()) {
        cout << "[";
        vs[i].print();
        cout << "]";
        cout << "(" << con[i].first << "," << con[i].second <<")";
      }
    }
  }
  bool exist(int a) {
    if (vs.size() == 0) {
      return (v == a);
    } else {
      REP(i,vs.size()) {
        if (vs[i].exist(a)) return 1;
      }
    }
    return 0;
  }
  bool connect(vector<pii> &res, int a) {
    // print();cout << endl;
    // cout << a << endl;
    // cout << ":" << exist(a) << endl;
    bool f = 0;
    if (vs.size() == 0) {
      f = v == a;
    } else {
      REP(i,vs.size()) {
        int ii = (i+1)%vs.size();
        if (vs[ii].exist(a)) {
          vs[ii].connect(res,a);
        } else {
          res.push_back(con[i]);
          vs[ii].connect(res,con[i].second);
        }
      }
    }
    return f;
  }
};

typedef vector<vector<int> > matrix;
const int inf = 1<<29;
  
void backward_traverse(int v, int s, int r, matrix &g,
                       vector<int> &no, vector< vector<int> > &comp,
                       vector<int> &prev, vector<int> &mcost,
                       vector<Node> &nodes, vector<pii> &edge,
                       vector<int> &mark, int &cost, bool &found) {
  const int n = g.size();
  if (mark[v]) {
    vector<int> temp = no;
    found = true;
    Node node;
    do {
      cost += mcost[v];
      node.con.push_back(edge[v]);
      v = prev[v];
      node.vs.push_back(nodes[v]);
      
      if (v != s) {
        while (comp[v].size() > 0) {
          no[comp[v].back()] = s;
          comp[s].push_back(comp[v].back());
          comp[v].pop_back();
        }
      }
    } while (v != s);
    reverse(ALL(node.vs));
    reverse(ALL(node.con));
    nodes[s] = node;
    for (int j = 0; j < n; ++j)
      if (j != r && no[j] == s)
        for (int i = 0; i < n; ++i)
          if (no[i] != s && g[i][j] < inf) {
            g[i][j] -= mcost[ temp[j] ];
          }
  }
  mark[v] = true;
  for (int i = 0; i < n; ++i)
    if (no[i] != no[v] && prev[ no[i] ] == v)
      if (!mark[ no[i] ] || i == s)
        backward_traverse(i, s, r, g,
                          no, comp, prev, mcost, nodes, edge, mark, cost, found);
}

int minimum_spanning_arborescence(int r, matrix g, vector<pii> &edges) {
  const int n = g.size();
  vector<int> no(n);
  vector< vector<int> > comp(n);
  vector<Node> nodes(n);
  for (int i = 0; i < n; ++i) {
    no[i] = i;
    comp[i].push_back(i);
    nodes[i].v = i;
  }
  int cost = 0;
  vector<int> pprev;
  while (1) {
    vector<int> prev(n, -1);
    vector<int> mcost(n, inf);
    vector<pii> edge(n);
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        if (j == r) continue;
        if (no[i] != no[j] && g[i][j] < inf) {
          if (g[i][j] < mcost[ no[j] ]) {
            mcost[ no[j] ] = g[i][j];
            prev[ no[j] ] = no[i];
            edge[no[j]] = pii(i,j);
          }
        }
      }
    }
    pprev = prev;
    bool stop = true;
    vector<int> mark(n);
    for (int i = 0; i < n; ++i) {
      if (i == r || mark[i] || comp[i].size() == 0) continue;
      bool found = false;
      backward_traverse(i, i, r, g,
                        no, comp, prev, mcost, nodes, edge, mark, cost, found);
      if (found) stop = false;
    }
    // cout << "cost " << cost << endl;
    // REP(i,n) {
    //   REP(j,n) {
    //     cout << g[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    // cout << "no: ";
    // FOR(it, no) cout << *it << " " ; cout << endl;
    // cout << "mcost: ";
    // FOR(it, mcost) cout << *it << " " ; cout << endl;
    
    // cout << "prev: ";
    // REP(i,n) cout << prev[i] << " "; cout << endl;
    // cout << "prevprev: ";
    // FOR(it, prevprev) cout << *it << " "; cout << endl;
    // cout << endl;
    // nodes[1].print(); cout << endl;
    if (stop) {
      int cnt = 0;
      REP(i,n) {
        if (prev[i] >= 0) {
          nodes[i].connect(edges, edge[i].second);
          // nodes[i].print();
          // cout << " " << edge[i].first << " " << edge[i].second <<endl;
          edges.push_back(pii(edge[i].first, edge[i].second));
          cost += mcost[i];
        }
        if (prev[no[i]] < 0) cnt++;
      }
      // FOR(it, edges) {
      //   cout << it->first << " " << it->second << endl;
      // }
      if (cnt != 1) return -1;
      return cost;
    }
  }
}

struct Edge {
  int src, dst;
  int weight;
  Edge(int src, int dst, int weight) :
    src(src),dst(dst),weight(weight) {}
  bool operator<(const Edge &rhs) const {
    return weight > rhs.weight;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

vector<int> dijkstra(const Graph &g, int s, vector<int> &prev) {
  int n = g.size();
  vector<int> dist(n,inf);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (prev[e.dst] != -1) continue;
    prev[e.dst] = e.src;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}

vector<int> buildPath(const vector<int> &prev, int t) {
  vector<int> path;
  for (int u = t; u >= 0; u = prev[u])
    path.push_back(u);
  reverse(ALL(path));
  return path;
}

string name[100];
int m[100];
int sum[100];
pii p[100000];

vector<int> dprev[100];

string tostr(pii a) {
  stringstream ss;
  ss << name[a.first] << " " << a.second;
  return ss.str();
}

int main() {
  int n;
  while(cin >> n) {
    sum[0] = 0;
    int N = 0;
    map<string, int > mp;
    for (int i=0; i<n; ++i) {
      cin >>name[i] >> m[i];
      sum[i+1] = sum[i] + m[i];
      mp[name[i]] = i;
      N += m[i];
    }
    int cnt = 0;
    for (int i=0; i<n; ++i) {
      for (int j=0; j<m[i]; ++j) {
        p[cnt++] = pii(i,j);
      }
    }
    int E;
    cin >> E;
    Graph g(N);
    for(int i=0; i<E; ++i) {
      string cs1,cs2;
      int v1,v2,c;
      cin >> cs1>>v1>>cs2>>v2>>c;
      int c1 = mp[cs1];
      int c2 = mp[cs2];
      int a = sum[c1] + v1;
      int b = sum[c2] + v2;
      g[a].push_back(Edge(a,b,c));
    }
    matrix mat(n,vector<int>(n));
    vector<int> prev;
    for (int i=0; i<n ;++i) {
      vector<int> dist = dijkstra(g, sum[i], dprev[i]);
      // FOR(it, dprev[i]) cout << "*" << *it; cout << endl;
      for (int j=0; j<n; ++j) {
        mat[i][j] = dist[sum[j]];
      }
    }
    // for (int i=0; i<n; ++i) {
    //   for (int j=0;j<n; ++j) {
    //     cout << mat[i][j] << " ";
    //   }
    //   cout << endl;
    // }
    int Q;
    cin >> Q;
    for (int i=0; i<Q; ++i) {
      string cs3;
      int v3;
      cin >> cs3 >> v3;
      int c3 = mp[cs3];
      int a = sum[c3] + v3;
      vector<int> dist = dijkstra(g, a, prev);
      int res = dist[sum[c3]];
      vector<pii> edges;
      int tmpres = minimum_spanning_arborescence(c3, mat, edges);
      int ans = res + tmpres;

      // cout << "prevprev : ";
      // FOR(it, prevprev) 
      //   cout << *it << " ";
      // cout << endl;

      if (res == inf || tmpres < 0)  {
        cout << "Impossible" << endl;
      } else {
        cout << ans << endl;
        vector<int> path = buildPath(prev, sum[c3]);
        REP(i,path.size()-1) {
          cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
        }
        FOR(it, edges) {
          int a = it->second;
          int b = it->first;
          int A = sum[a];

          vector<int> path = buildPath(dprev[b], A);
          REP(i,path.size()-1) {
            cout << tostr(p[path[i]]) << " " << tostr(p[path[i+1]]) << endl;
          }
        }
        
      }
      puts("-----");
    }
  }
}
accuracy: 0.4222222222222222
time_ms: 160
memory_kb: 4788
final_rank: 8

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <cctype>
#include <cassert>
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
#if defined(_MSC_VER) || __cplusplus > 199711L
#define aut(r,v) auto r = (v)
#else
#define aut(r,v) typeof(v) r = (v)
#endif
#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#define mset(m,v) memset(m,v,sizeof(m))
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
using namespace std;
typedef vector<int> vi; typedef pair<int,int> pii; typedef vector<pair<int,int> > vpii;
typedef long long ll; typedef vector<long long> vl; typedef pair<long long,long long> pll; typedef vector<pair<long long,long long> > vpll;
typedef vector<string> vs; typedef long double ld;
template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }
template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }

struct GetStrID {
	static const int MaxLen = 21;	//書き換えること！
	static const int Alphas = 26;	//書き換えること！
	typedef char Alpha;
	static const int EndAlpha = -1;

private:
	template<typename T>
	struct Trie {
		bool terminate;
		T val;
		Trie<T> *next[Alphas];

		Trie(): terminate(false) { memset(next, 0, sizeof(next)); }
		~Trie() { for(Alpha a = 0; a < Alphas; ++ a) delete next[a]; }

		void insert(Alpha *s, const T &v) {
			if(*s == EndAlpha) {
				terminate = true;
				val = v;
				return;
			}else {
				if(!next[*s])
					next[*s] = new Trie;
				return next[*s]->insert(s+1, v);
			}
		}
		bool find(Alpha *s, T &out_v) const {
			if(*s == EndAlpha) {
				if(terminate) {
					out_v = val;
					return true;
				}else return false;
			}
			return next[*s] && next[*s]->find(s+1, out_v);
		}
	};

public:
	GetStrID(const char *alphas): cnt(0) {
		assert(strlen(alphas) <= Alphas);
		memset(idx, -1, sizeof(idx));
		for(const char *p = alphas; *p; ++ p)
			idx[*p] = p - alphas;
	}
	char idx[128];
	Trie<int> trie;
	int cnt;

	void clear() { trie = Trie<int>(); cnt = 0; }
	int get(const char *x) {
		static char tmp[MaxLen+1];
		{	int i;
			for(i = 0; x[i]; i ++) tmp[i] = idx[x[i]];
			tmp[i] = EndAlpha;
		}
		int ret = -1;
		if(!trie.find(tmp, ret)) {
			ret = cnt ++;
			trie.insert(tmp, ret);
		}
		return ret;
	}
};

pair<int,int> detectCycle2(const vector<int> &f) {
	int n = f.size();
	vector<bool> ved(n);
	int power, lambda, tortoise, hare;
	outer:
	for(int s = 0;s < n;s++){
		if(!ved[s]){
			power = 1, lambda = 1;
			if(f[s] < 0)continue;
			tortoise = s;
			ved[s] = true;
			hare = f[s];
			while(tortoise != hare) {
				if(hare < 0)goto outer;
				ved[hare] = true;
				if(power == lambda) {
					tortoise = hare;
					power <<= 1;
					lambda = 0;
				}
				if(hare < 0)goto outer;
				hare = f[hare];
				lambda++;
			}
			if(lambda > 0){
				return mp(hare, lambda);
			}
		}
	}
	return mp(-1,-1);
}

typedef int Weight;
vector<int> buildMSA(const vector<vector<Weight> > &w, int root)
{
int n = w.size();
		
// critical graphをつくる
// root以外の全頂点に対し、そこに入る最小コスト辺を選ぶ
vi par(n, -1);
for(int i = 0;i < n;i++){
	if(i != root){
		Weight min = INF;
		int pi = -1;
		for(int j = 0;j < n;j++){
			if(j != i){
				if(min > w[j][i]){
					min = w[j][i];
					pi = j;
				}
			}
		}
		par[i] = pi;
	}
}
		
pii res = detectCycle2(par);
if(res.first != -1){
	// cycleが存在したら縮約
	vi map(n, -1);
	int shed = n-res.second;
	map[res.first] = shed;
			
	// cycleの要素を列挙
	Weight minc = w[par[res.first]][res.first];
	for(int k = par[res.first];k != res.first;k = par[k]){
		map[k] = shed;
		minc = min(minc, w[par[k]][k]);
	}
			
	// 縮約後のグラフとの対応
	vector<int> imap(n-res.second);
	int p = 0;
	for(int i = 0;i < n;i++){
		if(map[i] != shed){
			map[i] = p;
			imap[p] = i;
			p++;
		}
	}
			
	// 縮約後のグラフ
	vector<vector<Weight> > sw(shed+1, vector<Weight>(shed+1, INF));
			
	vi to(n); // cycle内の要素xで、辺i->xの最小weightを実現するもの
	vi from(n); // cycle内の要素xで、辺x->iの最小weightを実現するもの
	for(int i = 0;i < n;i++){
		if(map[i] != shed){
			for(int j = 0;j < n;j++){
				if(map[j] == shed){
					// 非cycle->cycle
					// weightを修正
					Weight V = w[i][j] - w[par[j]][j] + minc;
					if(sw[map[i]][shed] > V){
						sw[map[i]][shed] = V;
						to[i] = j;
					}
				}else{
					// 非cycle->非cycle
					sw[map[i]][map[j]] = w[i][j];
				}
			}
		}else{
			for(int j = 0;j < n;j++){
				if(map[j] != shed){
					// cycle->非cycle
					Weight V = w[i][j];
					if(sw[shed][map[j]] > V){
						sw[shed][map[j]] = V;
						from[j] = i;
					}
				}
			}
		}
	}
			
	vi smsa = buildMSA(sw, map[root]); // 再帰してMSAを求める。
	// cycle以外の頂点について、imap,fromに従って対応を戻す。
	for(int i = 0;i < shed;i++){
		if(smsa[i] == shed){
			par[imap[i]] = from[imap[i]]; // cycle->非cycle
		}else if(smsa[i] != -1){
			par[imap[i]] = imap[smsa[i]]; // 非cycle->非cycle
		}
	}
			
	// cycle内の頂点について、toに従って対応を戻す。
	int u = imap[smsa[shed]];
	par[to[u]] = u;
}
return par;
}

int n;
char name1[21], name2[21];
char names[26][21];
int ms[26];
int g[26][100][100];
int ginter[26][100][100];
int h[26][26];
int hg[26][26];
bool vis[26];
vector<pair<pii,pii> > anss;

int dfs(int c) {
	if(vis[c]) return 0;
	vis[c] = true;
	int r = 1;
	rep(d, n) if(h[c][d] < INF)
		r += dfs(d);
	return r;
}

void buildPath_g(int c, int s, int t) {
	int u = ginter[c][s][t];
	if(u == -1) {
		if(s != t) anss.push_back(mp(mp(c, c), mp(s, t)));
	}else buildPath_g(c, s, u), buildPath_g(c, u, t);
}

int main() {
	GetStrID country("abcdefghijklmnopqrstuvwxyz");
	scanf("%d", &n);
	rep(i, n) {
		scanf("%s%d", names[i], &ms[i]);
		country.get(names[i]);
	}
	int e;
	scanf("%d", &e);
	mset(g, INF);
	rep(c, n) rep(i, ms[c]) g[c][i][i] = 0;
	vector<pair<pii,pii> > edges;
	rep(i, e) {
		int v1, v2, cost;
		scanf("%s%d%s%d%d", name1, &v1, name2, &v2, &cost);
		int c1 = country.get(name1), c2 = country.get(name2);
		if(c1 == c2) {
			amin(g[c1][v1][v2], cost);
		}else {
			edges.pb(mp(mp(c1,c2),mp(v2,cost)));
		}
	}
	mset(ginter, -1);
	rep(c, n) {
		int m = ms[c];
		rep(k, m) rep(i, m) rep(j, m) {
			if(g[c][i][j] > g[c][i][k] + g[c][k][j]) {
				g[c][i][j] = g[c][i][k] + g[c][k][j];
				ginter[c][i][j] = k;
			}
		}
	}
	mset(h, INF);
	rep(c, n) h[c][c] = 0;
	each(i, edges) {
		int c1 = i->first.first, c2 = i->first.second;
		int v2 = i->second.first, cost = i->second.second;
		if(h[c1][c2] > cost + g[c2][v2][0]) {
			h[c1][c2] = cost + g[c2][v2][0];
			hg[c1][c2] = v2;
		}
	}
	vector<vi> hv(n, vi(n));
	rep(i, n) rep(j, n) hv[i][j] = h[i][j];
	int q;
	scanf("%d", &q);
	rep(ii, q) {
		int v;
		scanf("%s%d", name1, &v);
		int c = country.get(name1);
		bool ok = true;
		ok &= g[c][v][0] < INF;
		mset(vis, 0);
		ok &= dfs(c) == n;
		if(!ok) {
			puts("Impossible");
		}else {
			anss.clear();
			int cost = g[c][v][0];
			buildPath_g(c, v, 0);
			vi tree = buildMSA(hv, c);
			rep(i, n) if(i != c) {
				cost += hv[tree[i]][i];
				int v2 = hg[tree[i]][i];
				anss.push_back(mp(mp(tree[i], i), mp(0, v2)));
				buildPath_g(i, v2, 0);
			}
			printf("%d\n", cost);
//			sort(all(anss));
//			anss.erase(unique(all(anss)), anss.end());
			each(i, anss) {
				pii p = i->first, q = i->second;
				printf("%s %d %s %d\n",
					names[p.first], q.first,
					names[p.second], q.second);
			}
		}
		puts("-----");
	}
	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 4396
final_rank: 1

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <cctype>
#include <cassert>
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
#if defined(_MSC_VER) || __cplusplus > 199711L
#define aut(r,v) auto r = (v)
#else
#define aut(r,v) typeof(v) r = (v)
#endif
#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#define mset(m,v) memset(m,v,sizeof(m))
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
using namespace std;
typedef vector<int> vi; typedef pair<int,int> pii; typedef vector<pair<int,int> > vpii;
typedef long long ll; typedef vector<long long> vl; typedef pair<long long,long long> pll; typedef vector<pair<long long,long long> > vpll;
typedef vector<string> vs; typedef long double ld;
template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }
template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }

struct GetStrID {
	static const int MaxLen = 21;	//書き換えること！
	static const int Alphas = 26;	//書き換えること！
	typedef char Alpha;
	static const int EndAlpha = -1;

private:
	template<typename T>
	struct Trie {
		bool terminate;
		T val;
		Trie<T> *next[Alphas];

		Trie(): terminate(false) { memset(next, 0, sizeof(next)); }
		~Trie() { for(Alpha a = 0; a < Alphas; ++ a) delete next[a]; }

		void insert(Alpha *s, const T &v) {
			if(*s == EndAlpha) {
				terminate = true;
				val = v;
				return;
			}else {
				if(!next[*s])
					next[*s] = new Trie;
				return next[*s]->insert(s+1, v);
			}
		}
		bool find(Alpha *s, T &out_v) const {
			if(*s == EndAlpha) {
				if(terminate) {
					out_v = val;
					return true;
				}else return false;
			}
			return next[*s] && next[*s]->find(s+1, out_v);
		}
	};

public:
	GetStrID(const char *alphas): cnt(0) {
		assert(strlen(alphas) <= Alphas);
		memset(idx, -1, sizeof(idx));
		for(const char *p = alphas; *p; ++ p)
			idx[*p] = p - alphas;
	}
	char idx[128];
	Trie<int> trie;
	int cnt;

	void clear() { trie = Trie<int>(); cnt = 0; }
	int get(const char *x) {
		static char tmp[MaxLen+1];
		{	int i;
			for(i = 0; x[i]; i ++) tmp[i] = idx[x[i]];
			tmp[i] = EndAlpha;
		}
		int ret = -1;
		if(!trie.find(tmp, ret)) {
			ret = cnt ++;
			trie.insert(tmp, ret);
		}
		return ret;
	}
};

pair<int,int> detectCycle2(const vector<int> &f) {
	int n = f.size();
	vector<bool> ved(n);
	int power, lambda, tortoise, hare;
	outer:
	for(int s = 0;s < n;s++){
		if(!ved[s]){
			power = 1, lambda = 1;
			if(f[s] < 0)continue;
			tortoise = s;
			ved[s] = true;
			hare = f[s];
			while(tortoise != hare) {
				if(hare < 0)goto outer;
				ved[hare] = true;
				if(power == lambda) {
					tortoise = hare;
					power <<= 1;
					lambda = 0;
				}
				if(hare < 0)goto outer;
				hare = f[hare];
				lambda++;
			}
			if(lambda > 0){
				return mp(hare, lambda);
			}
		}
	}
	return mp(-1,-1);
}

typedef int Weight;
vector<int> buildMSA(const vector<vector<Weight> > &w, int root)
{
int n = w.size();
		
// critical graphをつくる
// root以外の全頂点に対し、そこに入る最小コスト辺を選ぶ
vi par(n, -1);
for(int i = 0;i < n;i++){
	if(i != root){
		Weight min = INF;
		int pi = -1;
		for(int j = 0;j < n;j++){
			if(j != i){
				if(min > w[j][i]){
					min = w[j][i];
					pi = j;
				}
			}
		}
		par[i] = pi;
	}
}
		
pii res = detectCycle2(par);
if(res.first != -1){
	// cycleが存在したら縮約
	vi map(n, -1);
	int shed = n-res.second;
	map[res.first] = shed;
			
	// cycleの要素を列挙
	Weight minc = w[par[res.first]][res.first];
	for(int k = par[res.first];k != res.first;k = par[k]){
		map[k] = shed;
		minc = min(minc, w[par[k]][k]);
	}
			
	// 縮約後のグラフとの対応
	vector<int> imap(n-res.second);
	int p = 0;
	for(int i = 0;i < n;i++){
		if(map[i] != shed){
			map[i] = p;
			imap[p] = i;
			p++;
		}
	}
			
	// 縮約後のグラフ
	vector<vector<Weight> > sw(shed+1, vector<Weight>(shed+1, INF));
			
	vi to(n); // cycle内の要素xで、辺i->xの最小weightを実現するもの
	vi from(n); // cycle内の要素xで、辺x->iの最小weightを実現するもの
	for(int i = 0;i < n;i++){
		if(map[i] != shed){
			for(int j = 0;j < n;j++){
				if(map[j] == shed){
					// 非cycle->cycle
					// weightを修正
					Weight V = w[i][j] - w[par[j]][j] + minc;
					if(sw[map[i]][shed] > V){
						sw[map[i]][shed] = V;
						to[i] = j;
					}
				}else{
					// 非cycle->非cycle
					sw[map[i]][map[j]] = w[i][j];
				}
			}
		}else{
			for(int j = 0;j < n;j++){
				if(map[j] != shed){
					// cycle->非cycle
					Weight V = w[i][j];
					if(sw[shed][map[j]] > V){
						sw[shed][map[j]] = V;
						from[j] = i;
					}
				}
			}
		}
	}
			
	vi smsa = buildMSA(sw, map[root]); // 再帰してMSAを求める。
	// cycle以外の頂点について、imap,fromに従って対応を戻す。
	for(int i = 0;i < shed;i++){
		if(smsa[i] == shed){
			par[imap[i]] = from[imap[i]]; // cycle->非cycle
		}else if(smsa[i] != -1){
			par[imap[i]] = imap[smsa[i]]; // 非cycle->非cycle
		}
	}
			
	// cycle内の頂点について、toに従って対応を戻す。
	int u = imap[smsa[shed]];
	par[to[u]] = u;
}
return par;
}

int n;
char name1[21], name2[21];
char names[26][21];
int ms[26];
int g[26][100][100];
int ginter[26][100][100];
int h[26][26];
int hinter[26][26];
int hg[26][26];
bool vis[26];
vector<pair<pii,pii> > anss;

int dfs(int c) {
	if(vis[c]) return 0;
	vis[c] = true;
	int r = 1;
	rep(d, n) if(h[c][d] < INF)
		r += dfs(d);
	return r;
}

void buildPath_g(int c, int s, int t) {
	int u = ginter[c][s][t];
	if(u == -1) {
		if(s != t) anss.push_back(mp(mp(c, c), mp(s, t)));
	}else buildPath_g(c, s, u), buildPath_g(c, u, t);
}

void buildPath_h(int s, int t) {
	int u = hinter[s][t];
	if(u == -1) {
		if(s != t) {
			int v = hg[s][t];
			anss.push_back(mp(mp(s, t), mp(0, v)));
			buildPath_g(t, v, 0);
		}
	}else buildPath_h(s, u), buildPath_h(u, t);
}

int main() {
	GetStrID country("abcdefghijklmnopqrstuvwxyz");
	scanf("%d", &n);
	rep(i, n) {
		scanf("%s%d", names[i], &ms[i]);
		country.get(names[i]);
	}
	int e;
	scanf("%d", &e);
	mset(g, INF);
	rep(c, n) rep(i, ms[c]) g[c][i][i] = 0;
	vector<pair<pii,pii> > edges;
	rep(i, e) {
		int v1, v2, cost;
		scanf("%s%d%s%d%d", name1, &v1, name2, &v2, &cost);
		int c1 = country.get(name1), c2 = country.get(name2);
		if(c1 == c2) {
			amin(g[c1][v1][v2], cost);
		}else {
			edges.pb(mp(mp(c1,c2),mp(v2,cost)));
		}
	}
	mset(ginter, -1);
	mset(hinter, -1);
	rep(c, n) {
		int m = ms[c];
		rep(k, m) rep(i, m) rep(j, m) {
			if(g[c][i][j] > g[c][i][k] + g[c][k][j]) {
				g[c][i][j] = g[c][i][k] + g[c][k][j];
				ginter[c][i][j] = k;
			}
		}
	}
	mset(h, INF);
	rep(c, n) h[c][c] = 0;
	each(i, edges) {
		int c1 = i->first.first, c2 = i->first.second;
		int v2 = i->second.first, cost = i->second.second;
		if(h[c1][c2] > cost + g[c2][v2][0]) {
			h[c1][c2] = cost + g[c2][v2][0];
			hg[c1][c2] = v2;
		}
	}
	rep(k, n) rep(i, n) rep(j, n) {
		if(h[i][j] > h[i][k] + h[k][j]) {
			h[i][j] = h[i][k] + h[k][j];
			hinter[i][j] = k;
		}
	}
	vector<vi> hv(n, vi(n));
	rep(i, n) rep(j, n) hv[i][j] = h[i][j];
	int q;
	scanf("%d", &q);
	rep(ii, q) {
		int v;
		scanf("%s%d", name1, &v);
		int c = country.get(name1);
		bool ok = true;
		ok &= g[c][v][0] < INF;
		mset(vis, 0);
		ok &= dfs(c) == n;
		if(!ok) {
			puts("Impossible");
		}else {
			anss.clear();
			int cost = g[c][v][0];
			buildPath_g(c, v, 0);
			vi tree = buildMSA(hv, c);
			rep(i, n) if(i != c) {
				cost += hv[tree[i]][i];
				buildPath_h(tree[i], i);
			}
			printf("%d\n", cost);
			each(i, anss) {
				pii p = i->first, q = i->second;
				printf("%s %d %s %d\n",
					names[p.first], q.first,
					names[p.second], q.second);
			}

		}
		puts("-----");
	}
	return 0;
}
accuracy: 0.4444444444444444
time_ms: 90
memory_kb: 4396
final_rank: 3