模考四T3《树多》求调

题面

3. 树多

题目ID:19177必做题文件操作100分

最新提交:

Wrong Answer

0 分

历史最高:

Runtime Error

15 分

时间限制: 4000ms

空间限制: 262144kB

输入文件名: seert.in

输出文件名: seert.out

题目描述

给定 n,kn,k 和 kk 棵有 nn 个点的树。对于每个点对 (i,j)(i,j),求出其在每棵树上的路径经过的点(含端点)的集大小。

输入格式

从文件 seert.in 中读入数据。

第一行两个正整数 n,kn,k。

接下来 k(n−1)k(n−1) 行,每 n−1n−1 行都表示一棵树,每行有一条边。

输出格式

输出到文件 seert.out 中。

nn 行,每行 nn 个数,表示点对 (i,j)(i,j) 的答案。

样例

Input 1

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

Output 1

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

样例解释

样例 1 解释

以 (1,2)(1,2) 为例,第一棵树中在路径上的点为 {1,2}{1,2},第二棵树中在路径上的点为{1,2,4}{1,2,4},第三棵树中在路径上的点为 {1,2,3}{1,2,3},取并集得到 {1,2,3,4}{1,2,3,4},大小为 44。

对于所有路径 (x,x)(x,x),由于其会且只会经过 xx 一个点,所以并集大小是 11。

样例 2 输入 / 输出

见下发文件 ex_seert2.in/ans,该样例满足测试点 3∼63∼6 的限制。

样例 3 输入 / 输出

见下发文件 ex_seert3.in/ans,该样例满足测试点 1313 的限制。

数据范围

测试点编号 n=n= k≤k≤ 特殊性质
1∼21∼2 5050 5050
3∼63∼6 399399 300300 AA
7∼117∼11 799799 300300 AA
1212 100100 300300
1313 400400 300300
14∼2014∼20 800800 300300

特殊性质 AA:满足这 kk 棵树均为链。注意 1 不一定是链的端点

对于全部的测试点,保证:

  • 1≤n≤800,1≤k≤3001≤n≤800,1≤k≤300。
  • 1≤u,v≤n1≤u,v≤n。

提示:nn 的末尾数字可以帮助你快速判断特殊性质。

额外提示:请注意常数因子对程序运行效率的影响。

附件

down.zip


有能力的大佬可以救助蒟蒻吗§(* ̄▽ ̄*)§

`红温`代码
#include <bits/stdc++.h>
using namespace std;
int n, k;
vector<int> tags;
vector<bool> vis;
vector<vector<int>> cnt;
vector<vector<vector<int>>> edgs;
int randint(int _a, int _b)
{
    static unsigned long long seed = random_device()();
    static auto rng = mt19937_64(seed);
    static auto res = uniform_int_distribution<int>(_a, _b);
    return res(rng);
}
void bfs(int tree, int x)
{
    int tag = randint(1, 32767);
    queue<int> q;
    vis[x] = 1;
    tags[x] += tag;
    q.push(x);
    while (!q.empty())
    {
        int hd = q.front();
        q.pop();
        for (int targ : edgs[tree][hd])
        {
            if (vis[targ])
                continue;
            vis[targ] = 1;
            tags[targ] += tag;
            q.push(targ);
        }
    }
}
int main()
{
#ifdef ONLINE_JUDGE
    freopen("seert.in", "r", stdin);
    freopen("seert.out", "w", stdout);
#endif
    cin.tie(&cout)->sync_with_stdio(0);
    cin >> n >> k;
    tags.resize(n + 1, 0);
    vis.resize(n + 1, 0);
    cnt.resize(n + 1, vector<int>(n + 1, n));
    edgs.resize(k + 1, vector<vector<int>>(n + 1));
    for (int i = 1; i <= k; i++)
    {
        for (int j = 1; j <= n - 1; j++)
        {
            int u, v;
            cin >> u >> v;
            edgs[i][u].push_back(v);
            edgs[i][v].push_back(u);
        }
    }
    for (int fr = 1; fr <= n; fr++)
    {
        fill(tags.begin(), tags.end(), 0);
        for (int i = 1; i <= k; i++)
        {
            fill(vis.begin(), vis.end(), 0);
            for (auto targ : edgs[i][fr])
            {
                vis[fr] = 1;
                bfs(i, targ);
            }
        }
    }
    for (int fr = 1; fr <= n; fr++)
    {
        for (int to = 1; to <= n; to++)
        {
            if (tags[fr] == tags[to])
                cnt[fr][to]--;
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
            cout << (i == j ?: cnt[i][j]) << ' ';
        cout << endl;
    }
    return 0;
}

较矢见谅

样例一:

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

正确输出:

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

目前输出:

1 4 4 4 5 
4 1 4 4 5
4 4 1 4 5
4 4 4 1 5
5 5 5 5 1