luoguP1629 邮递员送信

建一个正向图和反向图,(都存到一个地方,反向图的节点加 n 就好了),跑两边 Dijskra

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10,M = 1e5 + 10,INF = 0x3f3f3f3f;
typedef pair<int,int> PII;
typedef long long LL;
int e[M*2],ne[M*2],w[M*2],h[N*2],idx,n,m;
LL dist[N*2];
bool st[N*2];
void add(int a,int b,int c) {
    e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx ++;
}
void dij(int s) {
    for(int i = 1;i <= n * 2; ++i) dist[i] = INF;
    dist[s] = 0;
    priority_queue<PII,vector<PII>,greater<PII> > q;
    q.push(make_pair(0,s));
    while(q.size()) {
        auto ver = q.top().second;
        q.pop();
        if(st[ver]) continue;
        st[ver] = 1;
        for(int i = h[ver]; ~i;i = ne[i]) {
            int j = e[i];
            if(dist[j] > dist[ver] + w[i]) {
                dist[j] = dist[ver] + w[i];
                q.push(make_pair(dist[j],j));
            }
        }
    }
}
int main() {
    memset(h,-1,sizeof h);
    cin >> n >> m;
    for(int i = 0;i < m; ++i) {
        int a,b,c;
        cin >> a >> b >> c;
        add(a,b,c);// 正向边
        add(b + n,a + n,c);// 反向边
    }
    LL sum = 0;
    dij(1);
    for(int i = 2;i <= n; ++i) sum += dist[i];
    dij(1 + n);
    for(int i = 2 + n;i <= n * 2; ++i) sum += dist[i];
    cout << sum << endl;
    return 0;
}
posted @ 2020-06-21 18:30  lukelmouse  阅读(73)  评论(0编辑  收藏  举报