二次联通门 : BZOJ 1922: [Sdoi2010]大陆争霸
/* BZOJ 1922: [Sdoi2010]大陆争霸 最短路思路题 带限制的转移 _link[x] 记录的是当前城市有多少城市保护 记录两个距离 一个是到当前点的最短路 一个是最早能够进入当前点时间 每次枚举当前点的必到点 更新dis_2 若都炸完后加入堆中 则答案就是 max (dis_1[N], dis_2[N]); */ #include <cstring> #include <cstdio> #include <vector> #include <queue> #define Max 3050 void read (int &now) { now = 0; register char word = getchar (); while (word < ‘0‘ || word > ‘9‘) word = getchar (); while (word >= ‘0‘ && word <= ‘9‘) { now = now * 10 + word - ‘0‘; word = getchar (); } } inline int max (int a, int b) { return a > b ? a : b; } struct Edge_Data { int to; int dis; int next; }; struct Data_ { int Id; int dis; Data_ (int __Id, int __dis) : Id (__Id), dis (__dis) {}; bool operator < (const Data_ &now) const { return this->dis > now.dis; } Data_ () {}; }; int N, M; int number[Max]; int __link[Max][Max]; int count[Max]; int Answer; class Dijkstra_Type { private : Edge_Data edge[Max * 100]; int Edge_Count ; int edge_list[Max]; int dis_1[Max]; int dis_2[Max]; bool visit[Max]; public : inline void Insert_Edge (int from, int to, int dis) { Edge_Count ++; edge[Edge_Count].to = to; edge[Edge_Count].next = edge_list[from]; edge[Edge_Count].dis = dis; edge_list[from] = Edge_Count; } void Dijkstra (int Start, int End) { memset (dis_1, 0x3f, sizeof dis_1); std :: priority_queue <Data_> Queue; Queue.push (Data_ (Start, 0)); dis_1[1] = 0; Data_ now; register int Maxn, res; register int pos; while (!Queue.empty ()) { now = Queue.top (); Queue.pop (); if (visit[now.Id]) continue; visit[now.Id] = true; Maxn = max (dis_1[now.Id], dis_2[now.Id]); for (int i = edge_list[now.Id]; i; i = edge[i].next) if (dis_1[edge[i].to] > Maxn + edge[i].dis) { dis_1[edge[i].to] = Maxn + edge[i].dis; int res = max (dis_1[edge[i].to], dis_2[edge[i].to]); if (!number[edge[i].to]) Queue.push (Data_ (edge[i].to, res)); } for (int i = 1; i <= count[now.Id]; i ++) { pos = __link[now.Id][i]; number[pos] --; dis_2[pos] = max (dis_2[pos], Maxn); res = max (dis_1[pos], dis_2[pos]); if (!number[pos]) Queue.push (Data_ (pos, res)); } } Answer = max (dis_1[End], dis_2[End]); } }; Dijkstra_Type Make; int main (int argc, char *argv[]) { read (N); read (M); int x, y, z; for (int i = 1; i <= M; i ++) { read (x); read (y); read (z); if (x != y) Make.Insert_Edge (x, y, z); } for (int i = 1; i <= N; i ++) { read (number[i]); for (int pos = 1, x; pos <= number[i]; pos ++) { read (x); __link[x][++ count[x]] = i; } } Make.Dijkstra (1, N); printf ("%d", Answer); return 0; }
时间: 2024-10-08 10:29:16