[SDOI2010]大陆争霸 带限制最短路

首先明确最短路是DP 带继承的DP 是有转移的

bellman没有顺序的松弛 复杂度很高 dijk维护一个正解点集 很快

这道题给最短路加了限制:同时走若干条路,当走过某些点后才能走该点

原转移为:d[x] = min {d[y] + w | y -> x}

新加的转移为:d[x] = max {d[y] | y protect x}

可以知道 依然可以维护一个正解点集 当没有protect才可以加入点集

我犯的错误:

longlong

莫名TLE的原因很可能是数组开小 相信复杂度计算

 

可能会补充手写堆dijk

我TM显然是不会补了!!!!wtf lazyboy!  -State 010913

View Code
 1 #include <cstdio>
 2 #include <vector>
 3 #include <cstring>
 4 using namespace std;
 5 int n, m;
 6 typedef __int64 ll;
 7 const int N = 10000, M = 200000;
 8 const ll INF = 1LL << 60;
 9 int key[M], head[N], next[M], len[M], cnt, in[N];
10 ll d[N];
11 vector<int> vc[N];
12 vector<int>::iterator it;
13 inline void add (int x, int y, int w)
14 {
15     key[cnt] = y;
16     next[cnt] = head[x];
17     len[cnt] = w;
18     head[x] = cnt ++;
19 }
20 inline void dijk ()
21 {
22     bool v[N] = {};
23     for (int i = 0; i <= n; i ++)
24         d[i] = INF;
25     d[1] = 0;
26     for (int i = 1; i <= n; i ++)
27     {
28         int k = 0;
29         for (int j = 1; j <= n; j ++)
30             if (!v[j] && in[j] == 0 && d[j] < d[k])
31                 k = j;
32         v[k] = true;
33         if (k == n) break;
34         for (int j = head[k]; ~ j; j = next[j])
35             d[key[j]] = min (d[key[j]], d[k] + len[j]);
36         for (it = vc[k].begin (); it != vc[k].end (); it ++)
37         {
38             in[*it] --;
39             d[*it] = max (d[*it], d[k]);
40         }
41     }
42 }
43 int main ()
44 {
45     memset (head, -1, sizeof head);
46     scanf ("%d%d", &n, &m);
47     for (int i = 1, a, b, c; i <= m; i ++)
48         scanf ("%d%d%d", &a, &b, &c), add (a, b, c);
49     for (int i = 1, x, y; i <= n; i ++)
50     {
51         scanf ("%d", &x);
52         in[i] = x;
53         while (x --) scanf ("%d", &y), vc[y].push_back (i);
54     }
55     dijk ();
56     printf ("%I64d", d[n]);
57     return 0;
58 }
posted @ 2012-11-23 23:48  Moretimes  阅读(277)  评论(0编辑  收藏  举报