luogu P6822 [PA2012]Tax

https://www.luogu.com.cn/problem/P6822

是个NB套路题

首先把无向边变成两条有项边
然后边变成点,
新建一个超级起始点和终点
对于原图连向 1 1 1的点,全部连向超级起始点,连向 n n n的连向超级终点

对于每条边,连向自己的反向边,权值为边权大小

然后对于原图的每个点,把和它相连的边排个序,然后前一条边连向后一条边,边权为两边权值的差

这样跑出来的就是答案了

code:

#include<bits/stdc++.h>
#define N 400050
#define ll long long
using namespace std;
struct edge {
    int v, nxt; ll c;
} e[N << 2];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v, int c) { //printf("%d --> %d   %d\n", u, v, c);
    e[eid].v = v;
    e[eid].c = c;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}

struct A {
    ll dis; int id;
    bool operator < (const A &o) const {
        return dis > o.dis;
    }
};
priority_queue<A> q;
int vis[N], S, T;
ll dis[N];
void dij() {
    memset(dis, 0x3f, sizeof dis);
    dis[S] = 0, q.push((A){0, S});
    while(q.size()) {
        int u = q.top().id; q.pop();
        if(vis[u]) continue;
        vis[u] = 1;
        for(int i = p[u]; i + 1; i = e[i].nxt) {
            int v = e[i].v; ll c = e[i].c;
            if(dis[v] > dis[u] + c) {
                dis[v] = dis[u] + c;
                q.push((A){dis[v], v});
            }
        }
    }
  //  for(int i = 1; i <= T; i ++) printf("%lld ", dis[i]); printf("  *\n");
}
struct G {
    int v, c, id;
    bool operator < (const G &o) const {
        return c < o.c;
    }
};
vector<G> g[N];
int n, m;
int main() {
    init();
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i ++) {
        int u, v, c;
        scanf("%d%d%d", &u, &v, &c);
        g[u].push_back((G){v, c, i << 1});
        g[v].push_back((G){u, c, i << 1 | 1});
    }
    //S = 0, T = 1;
    S = m * 2 + 3, T = S + 1;
    for(int u = 1; u <= n; u ++) {
        sort(g[u].begin(), g[u].end());
        for(int i = 0; i < g[u].size(); i ++) {
            int v = g[u][i].v, id = g[u][i].id, c = g[u][i].c;
            insert(id ^ 1, id, c);
            if(u == 1) insert(S, id, c);
            if(v == n) insert(id, T, c);
        }
        for(int i = 1; i < g[u].size(); i ++) {
            int v = g[u][i].v, id = g[u][i].id, c = g[u][i].c;
            insert(id, g[u][i - 1].id, 0);
            insert(g[u][i - 1].id, id, c - g[u][i - 1].c);
        }
    }
    
    dij();
    printf("%lld", dis[T]);
    return 0;
}
posted @ 2021-10-14 07:21  lahlah  阅读(32)  评论(0编辑  收藏  举报