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\n", res[i]) : printf("Infinity\n");
    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('\n') : io.putstr("Infinity\n");
    return 0;
}

100-分层图排序

posted @ 2018-10-21 16:36  Grary  阅读(99)  评论(1编辑  收藏  举报
博客园 首页 私信博主 编辑 关注 管理 新世界