比赛 20191022轻松模拟测试 评测结果 AAAWWWWWWW
题目名称 原谅 最终得分 30
用户昵称 ziiidan 运行时间 2.085 s
代码语言 C++ 内存使用 46.08 MiB
提交时间 2019-10-22 18:17:02
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

const int maxn = 1e6 + 5;
const int INF = 0x7fffffff;

struct Edge {
    int x, y, nxt;
}e[maxn << 1 | 1];

struct Node {
    int u, w;
    bool operator < (const Node &rhs) const {
        return w < rhs.w;
    }
};

int n, m, cnt;
int S;
int fr, to;

int head[maxn], val[maxn];

bool vis[maxn], in[maxn];

priority_queue<Node> Q;

int read(void)
{
    int s = 0, w = 1;
    char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') w = -1;
    for(; ch <= '9' && ch >= '0'; ch = getchar()) s = s * 10 + ch - '0';
    return s * w;
}

inline void add(int x, int y)
{
    e[++cnt].x = x;
    e[cnt].y = y;
    e[cnt].nxt = head[x];
    head[x] = cnt;
}

bool check(int limit)
{
    memset(vis, false, sizeof(vis));
    memset(in, false, sizeof(in));
    vis[S] = true;
    while(!Q.empty()) Q.pop();
    Q.push((Node){S, val[S]});
    int num = 0;
    while(!Q.empty())
    {
        int x = Q.top().u;
        Q.pop();
        in[x] = true;
        num++;
        if(num == limit) break;
        for(int i = head[x]; i != -1; i = e[i].nxt)
        {
            int y = e[i].y;
            if(vis[y]) continue;
            Q.push((Node){y, val[y]});
            vis[y] = true;
        }
    }
    int minval = INF;
    for(int i = 1; i <= n; i++) if(in[i]) minval = min(minval, val[i]);
    for(int i = 1; i <= n; i++) if(!in[i]) if(val[i] > minval) return false;
    return true;
}

int main()
{
    freopen("green.in", "r", stdin);
    freopen("green.out", "w", stdout);
    memset(head, -1, sizeof(head));
    n = read(); m = read();
    int maxval = -INF;
    for(int i = 1; i <= n; i++)
    {
        val[i] = read();
        if(val[i] > maxval)
        {
            maxval = val[i];
            S = i;
        }
    }
    for(int i = 1; i < n; i++)
    {
        fr = read() + 1; to = read() + 1;
        add(fr, to);
        add(to, fr);
    }
    int L = 1, R = m;
    if(n <= 2000)
    {
        for(int i = m; i >= 1; i--)
        {
            if(check(i))
            {
                cout << i << '\n';
                return 0;
            }
        }
    }
    while(L + 1 < R)
    {
        int Mid = (L + R) >> 1;
        if(check(Mid)) L = Mid;
        else R = Mid - 1;
    }
    L = check(R) ? R : L;
    cout << R << '\n';
    return 0;
}