Problem D. Dwarf Tower spfa

http://codeforces.com/gym/100269/attachments

首先建图,然后图中每条边的权值是会变化的,是由dis[x] + dis[y]  --->   dis[make],然后就相当于新增加一个原点0,求0到1的最短距离

如果用了2更新4失败,但是2本来不是最优的,就是可以用7和8使得更优,那这样会不会漏掉最优解?答案是不会的,因为使用到7和8能更新2得时候,就会把2重新丢尽队列

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 2e5 + 20;
struct Edge {
    int u, v, w, tonext;
}e[maxn * 2];
int first[maxn], num;
void addEdge(int u, int v, int w) {
    ++num;
    e[num].u = u, e[num].v = v, e[num].w = w, e[num].tonext = first[u];
    first[u] = num;
}
LL dis[maxn];
int in[maxn], tim[maxn];
bool spfa(int bx, int n) { //从bx开始,有n个顶点
    queue<int> que;
    while (!que.empty()) que.pop();
    for (int i = 1; i <= n; ++i) {
        que.push(i);
        in[i] = true;
        tim[i]++;
    }
    while (!que.empty()) {
        int u = que.front();
        if (tim[u] > n) return true; //入队次数超过n次,出现负环
        que.pop();   //in[u] = false ?
        for (int i = first[u]; i; i = e[i].tonext) {
            if (dis[e[i].v] > dis[e[i].u] + dis[e[i].w]) {
                dis[e[i].v] = dis[e[i].u] + dis[e[i].w];
                if (!in[e[i].v]) { //不在队列
                    que.push(e[i].v);
                    in[e[i].v] = true;
                    tim[e[i].v]++;
                }
            }
        }
        in[u] = false;
    }
    return false;
}

void work() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        cin >> dis[i];
    }
    for (int i = 1; i <= m; ++i) {
        int f, x, y;
        cin >> f >> x >> y;
        addEdge(x, f, y);
        addEdge(y, f, x);
    }
    spfa(0, n);
    cout << dis[1] << endl;

}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    freopen("dwarf.in", "r", stdin);
    freopen("dwarf.out", "w", stdout);
    IOS;
    work();
    return 0;
}
View Code

也可以贪心。

每次都取一个权值最小的出来,因为那个已经不可能更小了,直接删除,然后更新其他。

用set维护。dp

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
struct Node {
    LL cost, id;
    bool operator < (const struct Node & rhs) const {
        if (cost != rhs.cost) return cost < rhs.cost;
        else return id < rhs.id;
    }
    Node(LL _cost, LL _id) {
        cost = _cost, id = _id;
    }
};
set<Node>ss;
const int maxn = 1e6 + 20;
LL dp[maxn];
vector<pair<int, int> > vc[maxn];
int getid[maxn];
void work() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        int val;
        cin >> val;
        dp[i] = val;
        ss.insert(Node(val, i));
    }
    for (int i = 1; i <= m; ++i) {
        int a, b, c;
        cin >> a >> b >> c;
        vc[c].push_back(make_pair(b, a));
        vc[b].push_back(make_pair(c, a));
    }
    set<Node> :: iterator it;
    while (!ss.empty()) {
        it = ss.begin();
        LL id = it->id;
        LL cost = it->cost;
        ss.erase(it);
        for (int i = 0; i < vc[id].size(); ++i) {
            int an = vc[id][i].first, to = vc[id][i].second;
            if (!ss.count(Node(dp[to], to))) {
                continue;
            }
            ss.erase(Node(dp[to], to));
            dp[to] = min(dp[to], cost + dp[an]);
            ss.insert(Node(dp[to], to));
        }
    }
    printf("%lld
", dp[1]);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#else
    freopen("dwarf.in","r",stdin);
    freopen("dwarf.out","w",stdout);
#endif
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7285879.html