题目大意:一群牛在一块农田的不同的点,现在他们都要去到同一个地方开会,然后现在从那个地方回到原来的位置,点与点之间的连线都是单向的,并且通过一个路径需要一定时间,问你现在哪只牛需要最多的时间?
这一题可以这么看,回来的时候可以是从汇点(开会的地方)去到不同点的最短距离,然后从不同的点去的时候可以看做从汇点沿着路径的反方向看怎么走最短时间。
这样看这一题就简单很多了,因为没有负边,直接Dijkstra算法,算两次即可
1 #include <iostream> 2 #include <functional> 3 #include <algorithm> 4 #define MAX_N 1001 5 #define MAX_T 10000000 6 7 using namespace std; 8 9 typedef int Position; 10 typedef struct edge_ 11 { 12 int to; 13 int cost; 14 Position next; 15 }Edge; 16 typedef struct node_ 17 { 18 Position point; 19 Position v; 20 int min_cost; 21 }Node; 22 23 static Node Gragh_Head[MAX_N]; 24 static Node Gragh_Head_rev[MAX_N]; 25 static Edge Gragh_Edge[MAX_N *MAX_N]; 26 static Edge Gragh_Edge_rev[MAX_N *MAX_N]; 27 static Node heap[MAX_N]; 28 static bool used[MAX_N]; 29 30 void Search_Dijkstra(const int, const int); 31 int Delete_Min(int *const); 32 void Insert(Position, Node); 33 34 int main(void) 35 { 36 int Node_sum, Path_sum, Goal_Farm, tmp_cost, tmp_to, tmp_start; 37 38 while (~scanf("%d%d%d", &Node_sum, &Path_sum, &Goal_Farm)) 39 { 40 for (int i = 0; i <= Node_sum; i++) 41 { 42 Gragh_Head[i].point = -1; 43 Gragh_Head_rev[i].point = -1; 44 } 45 for (int i = 0; i < Path_sum; i++)//邻接表储存 46 { 47 scanf("%d%d%d", &tmp_to, &tmp_start, &tmp_cost);//起点终点反过来 48 Gragh_Edge[i].to = tmp_to;//单向边,因为各个地方的牛要走到#X位置,相当于从#X走到各个点 49 Gragh_Edge[i].cost = tmp_cost; 50 Gragh_Edge[i].next = Gragh_Head[tmp_start].point; 51 Gragh_Head[tmp_start].point = i; 52 53 Gragh_Edge_rev[i].to = tmp_start;//反向边存在另一个图中 54 Gragh_Edge_rev[i].cost = tmp_cost; 55 Gragh_Edge_rev[i].next = Gragh_Head_rev[tmp_to].point; 56 Gragh_Head_rev[tmp_to].point = i; 57 } 58 Search_Dijkstra(Node_sum, Goal_Farm); 59 } 60 return 0; 61 } 62 63 void Insert(Position pos, Node goal) 64 { 65 Position s = pos, pr; 66 67 for (; s > 1; s = pr) 68 { 69 pr = s % 2 == 0 ? s >> 1 : (s - 1) >> 1; 70 if (heap[pr].min_cost > goal.min_cost) heap[s] = heap[pr]; 71 else break; 72 } 73 heap[s] = goal; 74 } 75 76 int Delete_Min(int *const size) 77 { 78 Position s1, s2, pr = 1, s; 79 Node out = heap[1], tmp = heap[(*size)--]; 80 81 for (; pr <= *size;) 82 { 83 s1 = pr << 1; s2 = s1 + 1; 84 if (s2 <= *size) 85 { 86 s = heap[s1].min_cost < heap[s2].min_cost ? s1 : s2; 87 heap[pr] = heap[s]; 88 pr = s; 89 } 90 else if (s1 <= *size) 91 { 92 heap[pr] = heap[s1]; pr = s1; 93 break; 94 } 95 else break; 96 } 97 Insert(pr, tmp); 98 return out.v; 99 } 100 101 void Search_Dijkstra(const int Node_sum, const int start) 102 { 103 int size = 0; 104 Position V, adj_v; 105 106 memset(used, 0, sizeof(used)); 107 for (int i = 1; i <= Node_sum; i++) 108 { 109 Gragh_Head[i].min_cost = MAX_T; 110 Gragh_Head[i].v = i; 111 } 112 Insert(++size, Gragh_Head[start]); 113 Gragh_Head[start].min_cost = 0; 114 115 while (size != 0) 116 { 117 V = Delete_Min(&size); 118 used[V] = 1; 119 for (int k = Gragh_Head[V].point; k != -1; k = Gragh_Edge[k].next) 120 { 121 adj_v = Gragh_Edge[k].to; 122 if (Gragh_Head[adj_v].min_cost > Gragh_Head[V].min_cost + Gragh_Edge[k].cost) 123 { 124 Gragh_Head[adj_v].min_cost = Gragh_Head[V].min_cost + Gragh_Edge[k].cost; 125 if (!used[adj_v]) 126 Insert(++size, Gragh_Head[adj_v]); 127 } 128 } 129 } 130 131 for (int i = 1; i <= Node_sum; i++) 132 { 133 Gragh_Head_rev[i].min_cost = MAX_T; 134 Gragh_Head_rev[i].v = i; 135 } 136 memset(used, 0, sizeof(used)); 137 size = 0;//堆从0开始,反向边开始 138 Insert(++size, Gragh_Head_rev[start]); 139 Gragh_Head_rev[start].min_cost = 0; 140 141 while (size != 0) 142 { 143 V = Delete_Min(&size); 144 used[V] = 1; 145 for (int k = Gragh_Head_rev[V].point; k != -1; k = Gragh_Edge_rev[k].next) 146 { 147 adj_v = Gragh_Edge_rev[k].to; 148 if (Gragh_Head_rev[adj_v].min_cost > Gragh_Head_rev[V].min_cost + Gragh_Edge_rev[k].cost) 149 { 150 Gragh_Head_rev[adj_v].min_cost = Gragh_Head_rev[V].min_cost + Gragh_Edge_rev[k].cost; 151 if (!used[adj_v]) 152 Insert(++size, Gragh_Head_rev[adj_v]); 153 } 154 } 155 } 156 int ans = -1; 157 for (int i = 1; i <= Node_sum; i++) 158 ans = max(ans, Gragh_Head[i].min_cost + Gragh_Head_rev[i].min_cost); 159 printf("%d ", ans); 160 }