【BZOJ1922】大陆争霸
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1922
涨姿势了,,,这下不只是复习了。。。
此题可以认为是一种变相的最短路,嗯,有限制条件的最短路。
设dist1[i]表示到达某个结点的最短时间,dist2[i]表示可以进入某个结点的最短时间,显然,真正进入的最短时间是max(dist1[i],dist2[i])。对于每一个用来更新其他结点的结点,我们用他实际进入的时间去更新与他相邻的城市的到达时间,依赖于他的城市的可进入时间,并且依赖于他的城市的入度减1。每次更新都要把入度为0的点加入优先队列,不管是原先就为0,还是减1后为0。
另外提一点,不要把读入优化直接传入参数,顺序会变!别问我怎么知道的。。。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 6 using namespace std; 7 8 inline int get_num() { 9 int num = 0; 10 char c = getchar(); 11 while (c < '0' || c > '9') c = getchar(); 12 while (c >= '0' && c <= '9') 13 num = num * 10 + c - '0', c = getchar(); 14 return num; 15 } 16 17 const int maxn = 3e3 + 5, maxm = 7e4 + 5, inf = 0x3f3f3f3f; 18 19 int head[maxn], eid, head2[maxn], eid2, ind[maxn]; 20 21 struct Edge { 22 int v, w, next; 23 } edge[maxm], edge2[maxm]; 24 25 inline void insert(int u, int v, int w) { 26 edge[++eid].v = v; 27 edge[eid].w = w; 28 edge[eid].next = head[u]; 29 head[u] = eid; 30 } 31 32 inline void insert2(int u, int v) { 33 edge2[++eid2].v = v; 34 edge2[eid2].next = head2[u]; 35 head2[u] = eid2; 36 } 37 38 int dist1[maxn], dist2[maxn], vis[maxn]; 39 40 struct node { 41 int id, dist; 42 node(int id, int dist) : id(id), dist(dist) {} 43 bool operator < (const node& rhs) const { 44 return dist > rhs.dist; 45 } 46 }; 47 48 priority_queue<node> q; 49 50 inline void dijkstra() { 51 memset(dist1, inf, sizeof(dist1)); 52 dist1[1] = 0; 53 q.push(node(1, 0)); 54 while (!q.empty()) { 55 int u = q.top().id; 56 q.pop(); 57 if (vis[u]) continue; 58 vis[u] = 1; 59 int td = max(dist1[u], dist2[u]); 60 for (int p = head[u]; p; p = edge[p].next) { 61 int v = edge[p].v, w = edge[p].w; 62 if (dist1[v] > td + w) { 63 dist1[v] = td + w; 64 if (!ind[v]) q.push(node(v, max(dist1[v], dist2[v]))); 65 } 66 } 67 for (int p = head2[u]; p; p = edge2[p].next) { 68 int v = edge2[p].v; 69 --ind[v], dist2[v] = max(dist2[v], td); 70 if (!ind[v]) q.push(node(v, max(dist1[v], dist2[v]))); 71 } 72 } 73 } 74 75 int main() { 76 int n = get_num(), m = get_num(); 77 for (int i = 1; i <= m; ++i) { 78 int u = get_num(), v = get_num(), w = get_num(); 79 if (u != v) insert(u, v, w); 80 } 81 for (int i = 1; i <= n; ++i) { 82 ind[i] = get_num(); 83 for (int j = 1; j <= ind[i]; ++j) { 84 int x = get_num(); 85 insert2(x, i); 86 } 87 } 88 dijkstra(); 89 printf("%d", max(dist1[n], dist2[n])); 90 return 0; 91 }