Gym - 102394E Exchanging Gifts (2019CCPC哈尔滨站 拓扑排序)

After the dress rehearsal of CCPC Harbin Site 2019, mm contestants are still in the contest arena. They are taking photos, discussing the problems, and exchanging gifts.

Initially, everyone has exactly one gift in their hand. Note that some contestants may have the same type of gifts. Specifically, the type of the gift in the ii-th contestant's hand can be represented as a positive integer gigi. Two contestants ii and j (1≤i,j≤m)j (1≤i,j≤m) share the same type of gifts if and only if gi=gjgi=gj holds.

There can be many rounds of gift exchanging between these mm contestants. In each round, two contestants may exchange their gifts with each other. Note that a pair of contestants can exchange gifts multiple times if they like. In the end, there will still be exactly one gift in each contestant's hand.

Let's denote hihi as the type of gift in the ii-th contestant's hand in the end. If gi≠higi≠hi holds, the ii-th contestant will be happy, because they have a different type of gift, otherwise they will be unhappy. Your task is to write a program to help them exchange gifts such that the number of happy contestants is maximized. For example, if g=[3,3,2,1,3]g=[3,3,2,1,3] and h=[1,2,3,3,3]h=[1,2,3,3,3], there will be 44 happy contestants.

Since mm can be extremely large, you will be given nn sequences s1,s2,…,sns1,s2,…,sn, and the sequence gg is equal to snsn. The ii-th (1≤i≤n)(1≤i≤n) sequence will be given in one of the following two formats:

  • "1 k q[1..k]" (1≤k≤1061≤k≤106, 1≤qi≤1091≤qi≤109): It means si=[q1,q2,…,qk]si=[q1,q2,…,qk].
  • "2 x y" (1≤x,y≤i−11≤x,y≤i−1): It means si=sx+sysi=sx+sy. Here "++" denotes concatenation of sequences, for example [3,3,2]+[2,2,3,3]=[3,3,2,2,2,3,3][3,3,2]+[2,2,3,3]=[3,3,2,2,2,3,3].

Input

The input contains multiple cases. The first line of the input contains a single integer TT (1≤T≤100001≤T≤10000), the number of cases.

For each case, the first line of the input contains a single integer nn (1≤n≤1061≤n≤106), denoting the number of sequences. Each of the next nn lines describes a sequence in one of the two formats defined in the problem statement, where the ii-th (1≤i≤n1≤i≤n) line describes the sequence sisi.

It is guaranteed that the sum of all nn over all cases does not exceed 106106, and the sum of kk over all cases does not exceed 106106. It is also guaranteed that no sequence has a length that exceeds 10181018.

Output

For each case, print a single line containing a single integer denoting the maximum number of happy contestants.

Example

Input

2
1
1 5 3 3 2 1 3
3
1 3 3 3 2
1 4 2 2 3 3
2 1 2

Output

4
6

题意:

有两种操作:(1)给定一个序列(2)给出一个序列由哪两个序列合并而成

共 n 个操作,求第 n 个序列。

思路:

序列 a、b 可以组成 x ,连边 x -> a、x -> b,跑一边拓扑排序,推出最终有贡献的序列被计数了多少次。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 7;

inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

inline void write(ll x)
{
    if(x < 0) x = -x, putchar('-');
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

vector<int>vec[N], mp[N];
ll cnt[N];
int in[N], n, op[N];
unordered_map<int, ll> ans;
bool vis[N];

void init() {
    ans.clear();
    for(int i = 1; i <= n; ++i) vec[i].clear();
    for(int i = 1; i <= n; ++i) mp[i].clear();
    for(int i = 1; i <= n; ++i) cnt[i] = 0;
    for(int i = 1; i <= n; ++i) in[i] = 0;
    for(int i = 1; i <= n; ++i) vis[i] = 0;
}

void bfs() {
    queue<int>q;
    q.push(n);
    vis[n] = 1;
    while(!q.empty()) {
        int top = q.front();
        q.pop();
        int siz = mp[top].size();
        for(int i = 0; i < siz; ++i) {
            int v = mp[top][i];
            in[v]++;
            if(!vis[v]) {
                q.push(v);
                vis[v] = 1;
            }
        }
    }
}

void topo() {
    queue<int>q;
    q.push(n);
    while(!q.empty()) {
        int top = q.front();
        q.pop();
        int siz = mp[top].size();
        for(int i = 0; i < siz; ++i) {
            int v = mp[top][i];
            in[v]--;
            cnt[v] += cnt[top];
            if(in[v] == 0) q.push(v);
        }
    }
}

void solve() {
    for(int i = 1; i <= n; ++i) {
        if(cnt[i] > 0 && op[i] == 1) {
            int siz = vec[i].size();
            for(int j = 0; j < siz; ++j)
                ans[vec[i][j]] += cnt[i];
        }
    }
    ll maxx = -inf, sum = 0;
    for(unordered_map<int, ll>::iterator it = ans.begin(); it != ans.end(); ++it) {
        sum += it -> second;
        if(maxx < it -> second) {
            maxx = it -> second;
        }
    }
    ll ans;
    if(maxx * 2 > sum) ans = (sum - maxx) * 2;
    else ans = sum;
    write(ans), printf("\n");
}

int main() {
    int t, k, a;
    t = read();
    while(t--) {
        init();
        n = read();
        for(int i = 1; i <= n; ++i) {
            op[i] = read();
            if(op[i] == 1) {
                k = read();
                for(int j = 1; j <= k; ++j) {
                    a = read();
                    vec[i].push_back(a);
                }
            }
            else {
                k = read(), a = read();
                mp[i].push_back(k), mp[i].push_back(a);
            }
        }
        cnt[n] = 1;
        bfs();
        topo();
        solve();
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/108777071