最小生成树裸题,考虑多加入一个虚拟节点,这个点到其他点的距离就是学会那个题所花费的时间。

https://ac.nowcoder.com/acm/contest/548/C

Code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
    int in;
    int to;
    int w;
}edge[6000005];
int que[1000005], tt[1000005], cnt;
namespace IO {
    char buf[1 << 15], *S, *T;
    inline char gc() {
        if (S == T) {
            T = (S = buf) + fread(buf, 1, 1 << 15, stdin);
            if (S == T)return EOF;
        }
        return *S++;
    }
    inline int read() {
        int x; bool f; char c;
        for (f = 0; (c = gc()) < '0' || c > '9'; f = c == '-');
        for (x = c ^ '0'; (c = gc()) >= '0' && c <= '9'; x = (x << 3) + (x << 1) + (c ^ '0'));
        return f ? -x : x;
    }
    inline long long readll() {
        long long x; bool f; char c;
        for (f = 0; (c = gc()) < '0' || c > '9'; f = c == '-');
        for (x = c ^ '0'; (c = gc()) >= '0' && c <= '9'; x = (x << 3) + (x << 1) + (c ^ '0'));
        return f ? -x : x;
    }
}
using IO::read;
using IO::readll;
int getf(int k)
{
    return que[k] == k ? k : que[k] = getf(que[k]);
}
void add(int a, int b, int c)
{
    edge[cnt++] = node{ a,b,c };
}
int main()
{
    int n, m, k, a, b, c;
    ll t;
    n = read(); m = read(); k = read(); t = readll();
    for (int i = 1; i <= n + 1; i++)
        que[i] = i;
    for (int i = 1; i <= n; i++)
        tt[i] = read();
    while (k--)
    {
        a = read();
        tt[a] = 0;
    }
    for (int i = 1; i <= n; i++)
        add(i, n + 1, tt[i]);
    while (m--)
    {
        a = read();
        b = read();
        c = read();
        add(a, b, c);
    }
    sort(edge, edge + cnt, [](node q, node w) {
        return q.w < w.w;
    });
    ll ans = 0;
    for (int i = 0; i < cnt; i++)
    {
        int q = getf(edge[i].in), w = getf(edge[i].to);
        if (q != w)
        {
            que[q] = w;
            ans += edge[i].w;
        }
    }
    puts(ans <= t ? "Yes" : "No");
}