Problem:
Problem G:
Entangled Tree
The electronics division in Ishimatsu Company consists of various development departments
for electronic devices including disks and storages, network devices, mobile phones, and many
others. Each department covers a wide range of products. For example, the department of disks
and storages develops internal and external hard disk drives, USB thumb drives, solid-state
drives, and so on. This situation brings staff in the product management division difficulty
categorizing these numerous products because of their poor understanding of computer devices.
One day, a staff member suggested a tree-based diagram named a
category diagram
in order to
make their tasks easier. A category diagram is depicted as follows. Firstly, they prepare one
large sheet of paper. Secondly, they write down the names of the development departments
on the upper side of the sheet. These names represent the
start nodes
of the diagram. Each
start node is connected to either a single
split node
or a single end node (these nodes will be
mentioned soon later). Then they write down a number of questions that distinguish features
of products in the middle, and these questions represent the split nodes of the diagram. Each
split node is connected with other split nodes and end nodes, and each line from a split node
is labeled with the answer to the question. Finally, they write down all category names on the
lower side, which represents the
end nodes
.
The classification of each product is done like the following. They begin with the start node that
corresponds to the department developing the product. Visiting some split nodes, they traces
the lines down until they reach one of the end nodes labeled with a category name. Then they
find the product classified into the resultant category.
The visual appearance of a category diagram makes the diagram quite understandable even for
non-geek persons. However, product managers are not good at drawing the figures by hand, so
most of the diagrams were often messy due to many line crossings. For this reason, they hired
you, a talented programmer, to obtain the
clean diagrams
equivalent to their diagrams. Here,
we mean the clean diagrams as those with no line crossings.
Your task is to write a program that finds the clean diagrams. For simplicity, we simply ignore
the questions of the split nodes, and use integers from 1 to
N
instead of the category names.
Input
The input consists of multiple datasets. Each dataset follows the format below:
N M Q
split node info
1
split node info
2
...
split node info
M
query
1
query
2
...
query
Q
The first line of each dataset contains three integers
N
(1 ≤
N
≤ 100000),
M
(0 ≤
M
≤
N
- 1),
and
Q
(1 ≤
Q
≤ 1000,
Q
≤
N
), representing the number of end nodes and split nodes, and the
number of queries respectively. Then
M
lines describing the split nodes follow. Each split node
is described in the format below:
Y L label
1
label
2
. . .
The first two integers,
Y
(0 ≤
Y
≤ 10
9
) and
L
, wh
...(truncated)

Submitted solutions:

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

#define x first
#define y second
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define FOR(i, a, b) for(int i = (int)(a); i < (int)(b); i++)
#define REP(i, a) FOR(i, 0, a)
#define TRACE(x) cout << #x << " " << x << endl
#define _ << " _ " <<

using namespace std;

//#define task "a"
#define oo 1e9

const int MAXM = 100010;

class inter {
 public:
  int h, l;
  vector<int> V;
  void reset() {
    h = l = 0;
    V.clear();
  }
} a[MAXM*2];

int n, m, q;
int par[MAXM*2];
vector<int> graf[MAXM*2];

int nadji(int x) {
  if (par[x] == x) return x;
  return par[x] = nadji(par[x]);
}

void spoji(int i1, int i2) {
  i1 = nadji(i1);
  i2 = nadji(i2);
  par[i1] = i2;
  //  printf("Spajam %d %d\n", i1, i2);
}

int cnt;
int sol[MAXM*2];
int bio[MAXM*2];

int mini[MAXM*2];

void DFS(int curr) {
  //  TRACE(curr);
  mini[curr] = oo;
  if (curr <= n) {
    mini[curr] = curr;
    //    sol[cnt++] = curr;
    //    bio[curr] = 1;
  }
  for (auto it: graf[curr]) {
    DFS(it);
    mini[curr] = min(mini[curr], mini[it]);
  }
sort(graf[curr].begin(), graf[curr].end(), [](const int &i1, const int &i2) { return mini[i1] < mini[i2]; });
}

void DFS2(int curr) {
if (curr <= n) {
sol[cnt++] = curr;
bio[curr] = 1;
}

for (auto it: graf[curr]) DFS2(it);

}

int main(){
  while(1==1) {
    cnt = 1;
    memset(sol, 0, sizeof sol);
    memset(bio, 0, sizeof bio);
    memset(mini, 0, sizeof mini);
    REP(i, MAXM*2) par[i] = i;
    //  freopen(task ".in", "r", stdin);
    //  freopen(task ".out", "w", stdout);

    scanf("%d%d%d", &n, &m, &q);
    if (n == 0 && m == 0 && q == 0) break;
    REP(i, m) {
      scanf("%d%d", &a[i].h, &a[i].l);
      REP(j, a[i].l) {
	int pom;
	scanf("%d", &pom);
	a[i].V.pb(pom);
      }
    }
    sort(a, a + m, [](const inter &i1, const inter &i2){ return i1.h > i2.h; });

    int tr = n + 1;
    REP(i, m) {
      REP(j, a[i].V.size()) {
	int pom = nadji(a[i].V[j]);
	graf[tr].pb(pom);
	//	printf("Edge %d %d\n", tr, pom);
	spoji(pom, tr);
      }
      tr++;
    }
    for (int i = tr - 1; i > 0; i--) {
      if (par[i] == i) {
	par[i] = tr;
	graf[tr].pb(i);
	//	printf("Edge %d %d\n", tr, i);     
      }
    }
    
    DFS(tr);
    DFS2(tr);
    //    FOR(i, 1, n+1) {
    //      if (bio[i] == 0) sol[cnt++] = i;
    //    }

    REP(i, q) {
      int pom;
      scanf("%d", &pom);
      printf("%d\n", sol[pom]);
    }

    REP(i, tr+1) {
      graf[i].clear();
      a[i].reset();
    }
    printf("\n");
  }
  
  
  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 32704
final_rank: 1

code_snippet: #include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>

using namespace std;

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define TRACE(x) cout << #x << " = " << x << endl
#define _ << " _ " <<

typedef long long llint;

const int MAX = 300100;

vector<pair<int, vector<int>>> g;
pair<int, vector<int>> v[MAX];
int dad[MAX], id[MAX];
int idx[MAX];
bool dead[MAX];

int findset(int x) {
  return x == dad[x] ? x : dad[x] = findset(dad[x]);
}

int pos;
void dfs(int x) {
  if (g[x].second.size() == 1) {
    idx[pos++] = g[x].first;
    return;
  }
  for (int y: g[x].second) dfs(y);
}

int main(void) {
  int n, m, q;
  while (scanf("%d %d %d", &n, &m, &q) == 3) {
    if (n == 0) break;

    REP(i, m) {
      scanf("%d", &v[i].first);
      int k; scanf("%d", &k);
      v[i].second.resize(k);
      REP(j, k) {
        scanf("%d", &v[i].second[j]);
        --v[i].second[j];
      }
    }

    sort(v, v + m);
    g.clear();
    REP(i, n) {
      g.push_back({i, {i}});
      id[i] = i;
      dad[i] = i;
      dead[i] = false;
    }

    for (int j = m-1; j >= 0; --j) {
      vector<int> w;
      for (int x: v[j].second) w.push_back(id[findset(x)]);
      sort(w.begin(), w.end(), [&] (const int& a, const int& b) {
          return g[a].first < g[b].first;
        }
      );
      
      int par = findset(v[j].second[0]);
      for (int x: v[j].second) dad[findset(x)] = par;
      id[par] = g.size();
      dead[g.size()] = false;
      for (int x: w) dead[x] = true;
      g.push_back({g[w[0]].first, w});
    }
    
    vector<int> w;
    REP(i, (int)g.size())
      if (!dead[i]) w.push_back(i);
    sort(w.begin(), w.end(), [&] (const int& a, const int& b) {
        return g[a].first < g[b].first;
      }
    );
    
    pos = 0;
    for (int x: w) dfs(x);

    REP(i, q) {
      int x;
      scanf("%d", &x); --x;
      printf("%d\n", idx[x]+1);
    }
    putchar('\n');
  }
  
  return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 32708
final_rank: 3

code_snippet: #include <stdio.h>
#include <assert.h>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define mp make_pair

#define NUM (120000)
int N, M, Q, Y[NUM];
vector<int> ls[NUM];
pair<int, int> ord[NUM];
int hi[NUM], p[NUM], c[NUM], f[NUM], b[NUM], ans[NUM];
vector<pair<int, int> > a[NUM];

void fix(int k) {
    sort(a[k].begin(), a[k].end());
    f[k] = a[k][0].first;
    c[k] = 0;
    rep (i, a[k].size()) c[k] += a[k][i].second == -1 ? 1 : c[a[k][i].second];
}

void build() {
    Y[M] = -1;
    rep (i, N) hi[i] = -1;
    rep (i, M+1) ord[i] = mp(Y[i], i);
    sort(ord, ord+M+1);
    for (int ik = M; ik > 0; ik--) {
        const int k = ord[ik].second;
        a[k].clear();
        p[k] = -1;
        rep (i, ls[k].size()) {
            const int ix = ls[k][i]-1;
            if (hi[ix] == -1) a[k].push_back(mp(ix, -1));
            else {
                a[k].push_back(mp(f[hi[ix]], hi[ix]));
                assert(p[hi[ix]] == -1);
                p[hi[ix]] = i;
            }
            hi[ix] = k;
        }
        fix(k);
    }
    a[M].clear();
    rep (i, N) if (hi[i] == -1) a[M].push_back(mp(i, -1));
    rep (i, M) if (p[i] == -1) a[M].push_back(mp(f[i], i));
    fix(M);
    b[M] = 0;
    rep (ik, M+1) {
        const int k = ord[ik].second;
        int z = b[k];
        rep (i, a[k].size()) {
            if (a[k][i].second == -1) {
                ans[z] = a[k][i].first;
                z++;
            }
            else {
                b[a[k][i].second] = z;
                z += c[a[k][i].second];
            }
        }
    }
}

int main() {
    for (;;) {
        scanf("%d%d%d", &N, &M, &Q);
        if (N == 0) return 0;
        rep (i, M) {
            scanf("%d", Y+i);
            int L;
            scanf("%d", &L);
            ls[i].resize(L);
            rep (j, L) scanf("%d", &ls[i][j]);
        }
        build();
        rep (i, Q) {
            int q;
            scanf("%d", &q);
            printf("%d\n", ans[q-1]+1);
        }
        printf("\n");
    }
}
accuracy: 1
time_ms: 420
memory_kb: 14000
final_rank: 2