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; }
也可以贪心。
每次都取一个权值最小的出来,因为那个已经不可能更小了,直接删除,然后更新其他。
用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; }