CF - 96D - Volleyball
题意:一个无向图,有n个点,m条边,每条边有距离w,每个点有两个属性(1、从这点出发能到的最远距离,2、从这点出发的费用(不论走多远都一样)),一个人要从点x到点y,问最小费用是多少。
题目链接:http://codeforces.com/problemset/problem/96/D
——>>前n次SPFA用来建图(以费用为权值重新建图),建好图好再一次SPFA求小最小费用。
要小心新图的边数,边数可能会增长得很快,这地方我开得不够大WA数次。。。
#include <cstdio> #include <queue> #include <cstring> using namespace std; const int maxn = 10000 + 10; const int maxm = 1000 * 1000; const long long INF = 0x3f3f3f3f3f3f3f3f; struct CSPFA{ int head[maxn], nxt[maxm], u[maxm], v[maxm], w[maxm], S, T, e; long long d[maxn]; bool inq[maxn]; void init(){ memset(head, -1, sizeof(head)); e = 0; } void addEdge(int uu, int vv, int ww){ u[e] = uu; v[e] = vv; w[e] = ww; nxt[e] = head[uu]; head[uu] = e; e++; } void spfa(int S){ memset(inq, 0, sizeof(inq)); memset(d, 0x3f, sizeof(d)); d[S] = 0; queue<int> qu; qu.push(S); while(!qu.empty()){ int x = qu.front(); qu.pop(); inq[x] = 0; for(int e = head[x]; e != -1; e = nxt[e]) if(d[v[e]] > d[x] + w[e]){ d[v[e]] = d[x] + w[e]; if(!inq[v[e]]){ qu.push(v[e]); inq[v[e]] = 1; } } } } }S1, S2; int main() { int n, m, x, y, i, j, uu, vv, ww, t, c; while(scanf("%d%d", &n, &m) == 2){ scanf("%d%d", &x, &y); S1.init(); for(i = 0; i < m; i++){ scanf("%d%d%d", &uu, &vv, &ww); S1.addEdge(uu, vv, ww); S1.addEdge(vv, uu, ww); } S2.init(); for(i = 1; i <= n; i++){ scanf("%d%d", &t, &c); S1.spfa(i); for(j = 1; j <= n; j++) if(S1.d[j] <= t){ S2.addEdge(i, j, c); } } S2.spfa(x); long long ret = S2.d[y] == INF ? -1 : S2.d[y]; printf("%I64d\n", ret); } return 0; }