[POI 2018] Plan Metra

[题目链接]

         https://www.lydsy.com/JudgeOnline/problem.php?id=5100

[算法]

         首先分两类考虑 :

         1. 1 -> N的路径不经过其它节点 , 我们只需判断(d1i - d2i)的绝对值是否全部相等

         2. 1 -> N的路径经过了其它节点 , 那么显然 , 1 -> N这条链的长度为min{ d1i + d2i } , 所有d1i + d2i等于链长的节点都在链上 , 将其余节点的d1i和d2i作差 , 即可O(1)判断出这个节点是挂在链上的哪个节点的 

         时间复杂度 : O(N)

[代码]

       

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 1e6 + 10;
const int inf = 2e9;
const int V = 1e7 + 10;

struct edge {
    int to , w , nxt;
} e[N << 1];

int n , m , tot;
int head[N] , d1[N] , d2[N] , mp[V];

template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void read(T &x) {
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f; 
}
inline void addedge(int u , int v , int w)
{
    ++tot;
    e[tot] = (edge){v , w , head[u]};
    head[u] = tot;
}
inline void add(int x , int y , int w) {
    addedge(x , y , w);
    addedge(y , x , w);
}
inline void dfs(int u , int par) {
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to , w = e[i].w;
        if (v != par) {
            printf("%d %d %d
" , u , v , w);
            dfs(v , u);
        }
    }
}
inline bool check()
{
    int val = abs(d1[2] - d2[2]);
    if (val == 0) return false;
    for (int i = 3; i < n; ++i)
        if (abs(d1[i] - d2[i]) != val) return false;
    printf("TAK
");
    printf("%d %d %d
" , 1 , n , val);
    for (int i = 2; i < n; ++i)
        if (d1[i] >= d2[i]) printf("%d %d %d
" , n , i , d2[i]);
        else printf("%d %d %d
" , 1 , i , d1[i]);
    return true;    
}
int main() {
    
    read(n);
    if (n == 2)
    {
        printf("TAK
");
        printf("%d %d %d
" , 1 , 2 , 1);
        return 0;
    }
    for (int i = 2; i < n; ++i) read(d1[i]);
    for (int i = 2; i < n; ++i) read(d2[i]);
    if (check()) 
        return 0;
    int line = inf;
    for (int i = 2; i < n; ++i) chkmin(line , d1[i] + d2[i]);
    mp[0] = 1;
    mp[line] = n;
    for (int i = 2; i < n; ++i) {
            if (d1[i] + d2[i] == line) {
                    if (mp[d1[i]] != 0) {
                            printf("NIE
");
                            return 0;
                    }
                    mp[d1[i]] = i;
            }
    }
    int pre = 0;
    for (int i = 1; i <= line; ++i) {
            if (mp[i]) {
                    add(mp[pre] , mp[i] , i - pre);
                    pre = i;
            }
    }
    for (int i = 2; i < n; ++i) {
            if (d1[i] + d2[i] - line != 0) {
                    int tmp = d1[i] + d2[i] - line;
                    if (tmp & 1) {
                            printf("NIE
");
                            return 0;
                    }
                    int len = d1[i] - tmp / 2;
                    if (len < 0 || mp[len] == 0) {
                            printf("NIE
");
                            return 0;
                    }
                    add(i , mp[len] , tmp / 2);
            }
    } 
    puts("TAK");
    dfs(1 , 0);
    
    return 0;
}
原文地址:https://www.cnblogs.com/evenbao/p/10778159.html