[USACO18DEC]Fine Dining

题面

\(Solution:\)

一开始想的是先跑一遍最短路,然后拆点之后再跑一遍,比较两次dis,然后发现拆点后会有负环(可能是我没想对拆点的方法),于是就放弃了拆点法。

我们考虑强制让每头牛选择走一条最短的,有草堆的路径,然后比较单纯的最短路。

然后就想到了分层图,在每一个有草垛的点向第二维图对应的点连一条单向的,权值为-美味值的边,这样第二维图上的dis就是每头牛选择走一条最短,有草堆的路径长度,再和第一维比较即可.注意有负边,跑某死亡算法.

\(Source\)

#include <set>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm>

using namespace std;

#define fir first
#define sec second
#define pb push_back
#define mp make_pair
#define LL long long
#define INF (0x3f3f3f3f)
#define mem(a, b) memset(a, b, sizeof (a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(x) cout << #x << " = " << x << endl
#define travle(i, x) for (register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
#define Forr(i, a, b) for (register int (i) = (a); (i) >= (b); -- (i))
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define ____ debug("go\n")

namespace io {
    static char buf[1<<21], *pos = buf, *end = buf;
    inline char getc()
    { return pos == end && (end = (pos = buf) + fread(buf, 1, 1<<21, stdin), pos == end) ? EOF : *pos ++; }
    inline int rint() {
        register int x = 0, f = 1;register char c;
        while (!isdigit(c = getc())) if (c == '-') f = -1;
        while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getc()));
        return x * f;
    }
    inline LL rLL() {
        register LL x = 0, f = 1; register char c;
        while (!isdigit(c = getc())) if (c == '-') f = -1;
        while (x = (x << 1ll) + (x << 3ll) + (c ^ 48), isdigit(c = getc()));
        return x * f;
    }
    inline void rstr(char *str) {
        while (isspace(*str = getc()));
        while (!isspace(*++str = getc()))
            if (*str == EOF) break;
        *str = '\0';
    }
    template<typename T> 
        inline bool chkmin(T &x, T y) { return x > y ? (x = y, 1) : 0; }
    template<typename T>
        inline bool chkmax(T &x, T y) { return x < y ? (x = y, 1) : 0; }    
}
using namespace io;

const int N = 5e4 + 2, M = 1e5 + 2;

int n, m, k;
int dis[N<<1];

namespace Gragh {
    int head[N<<1], ver[(M<<2) + N], nxt[(M<<2) + N], tot, edge[(M<<2) + N];
    inline void add(int u, int v, int w) {
        ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
    }
} using namespace Gragh;

bool vis[N<<1];

void SPFA(int st) {
    queue<int> q;
    memset(dis, 0x3f, sizeof dis);
    q.push(st);
    dis[st] = 0;
    vis[st] = 1;
    while (q.size()) {
        int u = q.front(); q.pop(); vis[u] = 0;
        for (register int i = head[u]; i; i = nxt[i]) {
            if (dis[ver[i]] > dis[u] + edge[i]) {
                dis[ver[i]] = dis[u] + edge[i];
                if (!vis[ver[i]]) {
                    vis[ver[i]] = 1;
                    q.push(ver[i]);
                }
            }   
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    file("Fine_Dining");
#endif
    n = rint(), m = rint(), k = rint();
    For (i, 1, m) {
        int u = rint(), v = rint(), w = rint();
        add(u, v, w); add(v, u, w);
        add(u + n, v + n, w); add(v + n, u + n, w);
    }
    For (i, 1, k) {
        int u = rint(), val = rint();
        add(u, u + n, -val);
    }
    SPFA(n);
    for (register int i = 1; i < n; ++ i) if (dis[i] >= dis[i + n]) {
        puts("1");
    } else puts("0");
}
posted @ 2019-03-05 19:14  茶Tea  阅读(175)  评论(0编辑  收藏  举报