• nowcoder 提高第六场A题


    Solution

    60分

    因为所有的字母要么全相同要么全不同, 所以两条路径比较字典序只需要比较第一条边就可以, 于是建反图, 在反图上按拓扑序转移就可以.
    因为有环, 所以拓扑完入度还是不为0的点答案为Infinity.

    #include <queue>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    const int N = 1e6 + 7;
    const long long mod = 998244353;
    
    struct Edge {
        int v, c; Edge* nxt;
        Edge(int _, int __, Edge* ___) : v(_), c(__), nxt(___) { }
    };
    Edge* head[N];
    int du[N];
    
    #define AddEdge(u, v, c) head[u] = new Edge(v, c, head[u])
    
    int vis[N], dis[N], res[N], path[N], len[N];
    
    int main () {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i += 1) {
            int u, v, c;
            scanf("%d%d%d", &u, &v, &c);
            AddEdge(v, u, c), du[u] += 1;
        }
        std:: queue<int> Que;
        for (int i = 1; i <= n; i += 1) 
            if (not du[i]) Que.push(i), vis[i] = true;
        while (not Que.empty()) {
            int u = Que.front(); Que.pop();
            for (auto edge = head[u]; edge; edge = edge->nxt) {
                int v = edge->v, c = edge->c;
                du[v] -= 1;
                if (not du[v]) Que.push(v), vis[v] = 1;
                if (dis[u] + 1 > dis[v]) 
                    dis[v] = dis[u] + 1, path[v] = u, len[v] = c, 
                    res[v] = (res[u] * 29ll % mod + c * 29ll % mod) % mod;
                if (dis[u] + 1 == dis[v] and c < len[v]) 
                    path[v] = u, len[v] = c, 
                    res[v] = (res[u] * 29ll % mod + c * 29ll % mod) % mod;
            }
        }
        for (int i = 1; i <= n; i += 1)
            vis[i] ? printf("%d
    ", res[i]) : printf("Infinity
    ");
        return 0;
    }
    

    100分-倍增

    剩下的40分难点在于比较路径字典序的大小.
    如何找出两条路径第一个不同的位置?
    可以用倍增, 具体就是预处理出点u向后走(1)个位置路径的hash值, 向后走(2)个位置路径的hash值, 向后走(2^k)个位置路径的hash值.
    考试的时候真的是没有想到呀, 于是就随便写了个玄学复杂度的东西来判路径,

    真TM难对拍, 我造了树还把边权设为(1, 2)才拍出错误, 最后发现时递推了向后走(2^i)个位置的hash值但是没有递推向后走(2^i)会走到哪个点.
    努力卡常才卡到1.3秒+.

    #include <ctype.h>
    #include <math.h>
    #include <queue>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    const int N = 1e6 + 7;
    const long long mod = 998244353;
    int L = 20;
    using std:: string;
    
    const int BUFSIZE = 1e6;
    char inbuf[BUFSIZE], outbuf[BUFSIZE], *si = inbuf, *ti = inbuf, *so = outbuf, *to = outbuf + BUFSIZE;
    struct FastIO {
        ~FastIO() {fwrite(outbuf, 1, so - outbuf, stdout);}
    #define gc()  (si==ti&&(ti=inbuf+fread(si=inbuf,1,BUFSIZE,stdin),si==ti)?EOF:*si++)
    #define pc(c) (so==to?fwrite(outbuf,1,BUFSIZE,stdout),so=outbuf,*so++=c:*so++=c)
        inline int rd() {
            char c, p = 0; int w;
            while (not isdigit(c = gc())); 
            for (w = c & 15; isdigit(c = gc()); w = w * 10 + (c & 15));
            return w;
        }
        template<typename T>inline void print(T w) {
            static char s[20]; int top = 0;
            if (w < 0)pc('-'), w = -w; if (w == 0)pc('0');
            for (top = 0; w; w /= 10)s[++top] = w % 10;
            while (top)pc(s[top--] | '0');
        }
        int putstr(const char* u) {
            int l = strlen(u);
            for (int i = 0; i < l; i += 1) pc(u[i]); return 0;
        }
    } io;
    #define read io.rd
    
    struct Edge {
        int v, c; Edge* nxt;
        Edge() {}
        Edge(int _, int __, Edge* ___) : v(_), c(__), nxt(___) { }
    } pool[N];
    Edge* head[N];
    int du[N];
    int cnt;
    #define new_Edge(a, b, c) (pool[cnt] = Edge(a, b, c), &pool[cnt++])
    #define AddEdge(u, v, c) du[v] += 1, head[u] = new Edge(v, c, head[u])
    
    int vis[N], dis[N], res[N], path[N], len[N];
    int hash[N][21], np[N][21];
    int Pow[21], que[N];
    bool Cmp(int u, int v) {
        for (int i = L; ~i; i -= 1)
            if (hash[u][i] == hash[v][i])
                u = np[u][i], v = np[v][i];
        return len[u] < len[v];
    }
    int main () {
        int n = read(), m = read(); L = std:: __lg(m);
        for (int i = 0, u, v, c; i < m; i += 1) {
            u = read(), v = read(), c = read();
            AddEdge(v, u, c);
        }
        Pow[0] = 29;
        for (int i = 1; i <= L; i += 1)
            Pow[i] = (1ll * Pow[i - 1] * Pow[i - 1]) % mod;
        int h = 0;
        for (int i = 1; i <= n; i += 1)
            if (not du[i]) que[++h] = i, vis[i] = true;
        while (h) {
            int u = que[h]; h -= 1;
            hash[u][0] = len[u], np[u][0] = path[u];
            for (int i = 1; i <= L; i += 1)
                np[u][i] = np[np[u][i - 1]][i - 1];
            for (int i = 1; i <= L; i += 1)
                hash[u][i] = (hash[u][i - 1] + hash[np[u][i - 1]][i - 1] * Pow[i - 1] % mod) % mod;
            for (auto edge = head[u]; edge; edge = edge->nxt) {
                int v = edge->v, c = edge->c;
                du[v] -= 1;
                if (not du[v]) que[++h] = v, vis[v] = 1;
                if (dis[u] + 1 == dis[v])
                    if ((c == len[v] and Cmp(u, path[v])) or c < len[v])
                        path[v] = u, len[v] = c,
                        res[v] = (res[u] * 29ll % mod + c * 29ll % mod) % mod;
                if (dis[u] + 1 > dis[v])
                    dis[v] = dis[u] + 1, path[v] = u, len[v] = c,
                    res[v] = (res[u] * 29ll % mod + c * 29ll % mod) % mod;
            }
        }
        for (int i = 1; i <= n; i += 1)
            vis[i] ? io.print(res[i]), pc('
    ') : io.putstr("Infinity
    ");
        return 0;
    }
    

    100-分层图排序

  • 相关阅读:
    js三大弹出消息框
    HDU
    BZOJ 1101 Zap 莫比乌斯反演
    竞赛常用STL备忘录
    K-query SPOJ
    HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改
    2018 Multi-University Training Contest
    多校补完计划 2017-02
    CodeForces 931C Laboratory Work 水题,构造
    CodeForces 937D 936B Sleepy Game 有向图判环,拆点,DFS
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/9825541.html
Copyright © 2020-2023  润新知