求助!需要帮忙卡常数……
查看原帖
求助!需要帮忙卡常数……
67387
Mosklia楼主2018/10/17 15:34

提交了好多次,每次都是随机在最后 3 个点中 TLE ……
这是最后一次提交的代码,语言标准 C++ 11 才过,换回 C++ 98 继续TLE ……

#include <cstring>
#include <cstdio>
#include <cctype>
#include <ext/pb_ds/priority_queue.hpp>

int readInt() {
    int temp = 0;
    char ch = '\0';
    while (!isdigit(ch = getchar()))
        continue;
    do
        temp = temp * 10 + ch - '0';
    while (isdigit(ch = getchar()));
    return temp;
}

struct HeapNode;
typedef __gnu_pbds::priority_queue<HeapNode> Heap;
typedef Heap::point_iterator Iterator;
typedef long long LL;

struct Point {
    int head;
    int dist;
    bool vis;

    Point() : head(0), dist(0X3F3F3F3F), vis(false) {}
} posi_pts[100001], nega_pts[100001], final_pts[100001];
struct Path {
    int next, from, to, cost;

    Path(int n = 0, int u = 0, int v = 0, int c = 0) : next(n), from(u), to(v), cost(c) {}
} posi_g[200001], nega_g[200001], final_g[200001];
const Point plain_point;
const Path plain_path;

struct HeapNode {
    int id;
    int dist;

    HeapNode(int a, int b) : id(a), dist(b) {}

    inline bool operator< (const HeapNode &hp) const {
        if (dist != hp.dist) return dist > hp.dist;
        return id > hp.id;
    }
};

LL dp[51][100001];
Iterator it[100001];
bool vis[51][100001], check[51][100001], res;
int ptr, n, m, p, k;
int min_dist;

inline void setPath(int u, int v, int c) {
    ++ptr;
    posi_g[ptr] = Path(posi_pts[u].head, u, v, c), posi_pts[u].head = ptr;
    nega_g[ptr] = Path(nega_pts[v].head, v, u, c), nega_pts[v].head = ptr;
}
inline void setFinalPath(int u, int v, int c) {
    final_g[++ptr] = Path(final_pts[u].head, u, v, c), final_pts[u].head = ptr;
}

void Dijkstra(int s, Point *pt, Path *ph) {
    static Heap q;
    q.push(HeapNode(s, 0));
    pt[s].dist = 0;
    for (int i = 1; i <= n; ++i)
        it[i] = Iterator();
    while (!q.empty()) {
        HeapNode p = q.top();
        q.pop(), pt[p.id].vis = true;
        for (int i = pt[p.id].head; i; i = ph[i].next) {
            int x = ph[i].to;
            LL cost = ph[i].cost;
            if (pt[x].vis) continue;
            if (pt[x].dist > p.dist + cost) {
                pt[x].dist = p.dist + cost;
                if (it[x] == 0)
                    it[x] = q.push(HeapNode(x, pt[x].dist));
                else
                    q.modify(it[x], HeapNode(x, pt[x].dist));
            }
        }
    }
}

LL DFS(int dist, int pos) {
    if (check[dist][pos])
        return dp[dist][pos];
    if (vis[dist][pos])
        return res = true;
    vis[dist][pos] = true;
    for (int i = final_pts[pos].head; i; i = final_g[i].next) {
        int x = final_g[i].to, c = final_g[i].cost;
        if (dist + c > k) continue;
        dp[dist][pos] += DFS(dist + c, x);
        dp[dist][pos] %= p;
    }
    vis[dist][pos] = false;
    check[dist][pos] = true;
    return dp[dist][pos];
}

int main() {
    int case_cnt = readInt();
    while (case_cnt--) {
        n = readInt(), m = readInt(), k = readInt(), p = readInt();
        for (int i = 1; i <= m; ++i) {
            int u = readInt(), v = readInt(), c = readInt();
            setPath(u, v, c);
        }
        Dijkstra(1, posi_pts, posi_g);
        Dijkstra(n, nega_pts, nega_g);
        min_dist = posi_pts[n].dist, ptr = 0;
        for (int i = 1; i <= m; ++i) {
            int u = posi_g[i].from, v = posi_g[i].to;
            if (posi_pts[u].dist + nega_pts[u].dist <= min_dist + k
             && posi_pts[u].dist + nega_pts[v].dist + nega_g[i].cost <= min_dist + k)
                setFinalPath(u, v, posi_pts[u].dist + nega_g[i].cost - posi_pts[v].dist);
        }
        for (int i = 0; i <= k; ++i)
            dp[i][n] = 1;
        int ans = DFS(0, 1);
        printf("%lld\n", (res ? -1LL : ans));
        for (int i = 0; i <= k; ++i)
        for (int j = 1; j <= n; ++j)
            dp[i][j] = 0;
        for (int i = 0; i <= k; ++i)
        for (int j = 1; j <= n; ++j)
            check[i][j] = false;
        for (int i = 1; i <= n; ++i)
            posi_pts[i] = plain_point;
        for (int i = 1; i <= n; ++i)
            nega_pts[i] = plain_point;
        for (int i = 1; i <= n; ++i)
            final_pts[i] = plain_point;
        for (int i = 1; i <= m; ++i)
            posi_g[i] = plain_path;
        for (int i = 1; i <= m; ++i)
            nega_g[i] = plain_path;
        for (int i = 1; i <= m; ++i)
            final_g[i] = plain_path;
       ptr = 0, res = false;
    }
    return 0;
}
2018/10/17 15:34
加载中...