F. Traveling

Solution

构造题,注意细节。
考虑怎么样构造用的边数最少,然后如果m更大就加一些不影响任何最短路的边,如果两两连边还是不够m条就输出No。
首先考虑直接从1到n的最短路,显然必须有d[1]=d[n]=min{d[i]}d[1]=d[n]=min\{d[i]\}
怎么用最少的边来构造呢?首先1到n我们直接连长度为d[n]d[n]的边,然后考虑2n12\sim n-1的所有点,将这些点按dd从小到大排序。
顺着考虑这些点,如果d[i]d[n](mod2)d[i]\equiv d[n]\pmod 2,那么我们只需要添加连接1和ii的边,边权为d[i]d[n]2\dfrac{d[i]-d[n]}{2}
比较麻烦的是如果d[i]≢d[n](mod2)d[i]\not\equiv d[n]\pmod 2,考虑添加两条边,分别是连接1和ii的边、连接iinn的边,边权如何确定?设两条边权分别为a,ba,b,我们希望走的路径是从1直接走到ii再直接走到nn,那么就不能出现从1走到nn再走到ii,或者从ii走到1再走到nn的情况,为了保证这一点就需要a+d[n]ba+d[n]\ge bb+d[n]ab+d[n]\ge a,也就是我们需要ab\left|a-b\right|尽量小,因此考虑a=d[i]2,b=d[i]2a=\left\lfloor\dfrac{d[i]}{2}\right\rfloor,b=\left\lceil\dfrac{d[i]}{2}\right\rceil,如果此时不满足d[n]bad[n]\ge b-a,那么实际上是不可能存在合适的GG能满足最短路是d[i]d[i]的,直接判为No,否则就可以连这两条边。
那么是不是对所有这样的点都连两条边呢?实际上考虑第一次连两条边的点是yy,那么一定满足d[y]d[i](mod2)d[y]\equiv d[i]\pmod 2,因此可以连接iiyy,边权为d[i]d[y]2\dfrac{d[i]-d[y]}{2},这样就只需要连一条边了。
时间复杂度O(min(n2,m)logn)O(\min(n^2,m)\log n)

vector<pair<int, int> >a;
int d[N];
map<pair<int, int>, bool>mp;

int main() {
    int n = fast_IO::read(), m = fast_IO::read();
    for (int i = 1; i <= n; ++i) {
        d[i] = fast_IO::read();
        a.push_back(make_pair(d[i], i));
    }
    int minn = INF;
    for (int i = 1; i <= n; ++i)minn = min(minn, d[i]);
    if (d[1] != d[n] || d[1] != minn) {
        puts("No");
        return 0;
    }
    sort(a.begin(), a.end());
    vector<tuple<int, int, int> >ans;
    int last = 0;
    for (auto [dist, y] : a) {
        if (y == 1)continue;
        if (y == n) {
            ans.push_back(make_tuple(1, n, d[n]));
            mp[make_pair(1, n)] = true;
        }
        else if ((dist & 1) == (d[n] & 1)) {
            ans.push_back(make_tuple(1, y, dist - d[n] >> 1));
            mp[make_pair(1, y)] = true;
        }
        else {
            if (!last) {
                int a = dist / 2;
                int b = (dist + 1) / 2;
                if (a + d[n] >= b) {
                    ans.push_back(make_tuple(1, y, a));
                    ans.push_back(make_tuple(y, n, b));
                    mp[make_pair(1, y)] = true;
                    mp[make_pair(y, n)] = true;
                }
                else {
                    puts("No");
                    return 0;
                }
            }
            else {
                if (last < y) {
                    ans.push_back(make_tuple(last, y, dist - d[last] >> 1));
                    mp[make_pair(last, y)] = true;
                }
                else {
                    ans.push_back(make_tuple(y, last, dist - d[last] >> 1));
                    mp[make_pair(y, last)] = true;
                }
            }
            last = y;
        }
    }
    if (m < ans.size()) {
        puts("No");
        return 0;
    }
    m -= ans.size();
    int nowx = 1, nowy = 2;
    while (m && nowx <= n) {
        if (!mp.count(make_pair(nowx, nowy))) {
            ans.push_back(make_tuple(nowx, nowy, 1000000000));
            --m;
        }
        ++nowy;
        if (nowy > n)++nowx, nowy = nowx + 1;
    }
    if (m) {
        puts("No");
        return 0;
    }
    puts("Yes");
    for (auto [x, y, z] : ans)
        printf("%d %d %d\n", x, y, z);
    return 0;
}