ShortestPath:Silver Cow Party(POJ 3268)
2015-10-26 12:43
696 查看
牛的聚会
题目大意:一群牛在一块农田的不同的点,现在他们都要去到同一个地方开会,然后现在从那个地方回到原来的位置,点与点之间的连线都是单向的,并且通过一个路径需要一定时间,问你现在哪只牛需要最多的时间?
这一题可以这么看,回来的时候可以是从汇点(开会的地方)去到不同点的最短距离,然后从不同的点去的时候可以看做从汇点沿着路径的反方向看怎么走最短时间。
这样看这一题就简单很多了,因为没有负边,直接Dijkstra算法,算两次即可
#include <iostream> #include <functional> #include <algorithm> #define MAX_N 1001 #define MAX_T 10000000 using namespace std; typedef int Position; typedef struct edge_ { int to; int cost; Position next; }Edge; typedef struct node_ { Position point; Position v; int min_cost; }Node; static Node Gragh_Head[MAX_N]; static Node Gragh_Head_rev[MAX_N]; static Edge Gragh_Edge[MAX_N *MAX_N]; static Edge Gragh_Edge_rev[MAX_N *MAX_N]; static Node heap[MAX_N]; static bool used[MAX_N]; void Search_Dijkstra(const int, const int); int Delete_Min(int *const); void Insert(Position, Node); int main(void) { int Node_sum, Path_sum, Goal_Farm, tmp_cost, tmp_to, tmp_start; while (~scanf("%d%d%d", &Node_sum, &Path_sum, &Goal_Farm)) { for (int i = 0; i <= Node_sum; i++) { Gragh_Head[i].point = -1; Gragh_Head_rev[i].point = -1; } for (int i = 0; i < Path_sum; i++)//邻接表储存 { scanf("%d%d%d", &tmp_to, &tmp_start, &tmp_cost);//起点终点反过来 Gragh_Edge[i].to = tmp_to;//单向边,因为各个地方的牛要走到#X位置,相当于从#X走到各个点 Gragh_Edge[i].cost = tmp_cost; Gragh_Edge[i].next = Gragh_Head[tmp_start].point; Gragh_Head[tmp_start].point = i; Gragh_Edge_rev[i].to = tmp_start;//反向边存在另一个图中 Gragh_Edge_rev[i].cost = tmp_cost; Gragh_Edge_rev[i].next = Gragh_Head_rev[tmp_to].point; Gragh_Head_rev[tmp_to].point = i; } Search_Dijkstra(Node_sum, Goal_Farm); } return 0; } void Insert(Position pos, Node goal) { Position s = pos, pr; for (; s > 1; s = pr) { pr = s % 2 == 0 ? s >> 1 : (s - 1) >> 1; if (heap[pr].min_cost > goal.min_cost) heap[s] = heap[pr]; else break; } heap[s] = goal; } int Delete_Min(int *const size) { Position s1, s2, pr = 1, s; Node out = heap[1], tmp = heap[(*size)--]; for (; pr <= *size;) { s1 = pr << 1; s2 = s1 + 1; if (s2 <= *size) { s = heap[s1].min_cost < heap[s2].min_cost ? s1 : s2; heap[pr] = heap[s]; pr = s; } else if (s1 <= *size) { heap[pr] = heap[s1]; pr = s1; break; } else break; } Insert(pr, tmp); return out.v; } void Search_Dijkstra(const int Node_sum, const int start) { int size = 0; Position V, adj_v; memset(used, 0, sizeof(used)); for (int i = 1; i <= Node_sum; i++) { Gragh_Head[i].min_cost = MAX_T; Gragh_Head[i].v = i; } Insert(++size, Gragh_Head[start]); Gragh_Head[start].min_cost = 0; while (size != 0) { V = Delete_Min(&size); used[V] = 1; for (int k = Gragh_Head[V].point; k != -1; k = Gragh_Edge[k].next) { adj_v = Gragh_Edge[k].to; if (Gragh_Head[adj_v].min_cost > Gragh_Head[V].min_cost + Gragh_Edge[k].cost) { Gragh_Head[adj_v].min_cost = Gragh_Head[V].min_cost + Gragh_Edge[k].cost; if (!used[adj_v]) Insert(++size, Gragh_Head[adj_v]); } } } for (int i = 1; i <= Node_sum; i++) { Gragh_Head_rev[i].min_cost = MAX_T; Gragh_Head_rev[i].v = i; } memset(used, 0, sizeof(used)); size = 0;//堆从0开始,反向边开始 Insert(++size, Gragh_Head_rev[start]); Gragh_Head_rev[start].min_cost = 0; while (size != 0) { V = Delete_Min(&size); used[V] = 1; for (int k = Gragh_Head_rev[V].point; k != -1; k = Gragh_Edge_rev[k].next) { adj_v = Gragh_Edge_rev[k].to; if (Gragh_Head_rev[adj_v].min_cost > Gragh_Head_rev[V].min_cost + Gragh_Edge_rev[k].cost) { Gragh_Head_rev[adj_v].min_cost = Gragh_Head_rev[V].min_cost + Gragh_Edge_rev[k].cost; if (!used[adj_v]) Insert(++size, Gragh_Head_rev[adj_v]); } } } int ans = -1; for (int i = 1; i <= Node_sum; i++) ans = max(ans, Gragh_Head[i].min_cost + Gragh_Head_rev[i].min_cost); printf("%d\n", ans); }