/* *State: POJ3268 Accepted 3324K 16MS C++ 1947B *题目大意: * 给定一个有向图(可带环),然后要求所有点到特定点e的距离,然后规定每个 * 点到e之后,还要返回原地,注意图是有向图,去跟回来的路径可能不同。 *解题思路: * 为了减少运算时间,可以建立正图跟反图,然后两遍spfa即可求解。
* 各种最短路均可求,注意复杂度即可。 */
spfa+邻接表:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <queue> using namespace std; const int MAXN = 1005; const int MAXE = 100005; const int inf = 0x3f3f3f3f; typedef struct _node { int v, w; int next; int op; _node(): op(0) {} }N; N edge[2 * MAXE]; int head[MAXN], cntEdge, endDis[MAXN]; void init(int n) { cntEdge = 0; for(int i = 0; i <= n; i++) { head[i] = -1; } } void addEdge(int u, int v, int w) { edge[cntEdge].v = v; edge[cntEdge].w = w; edge[cntEdge].op = 0; edge[cntEdge].next = head[u]; head[u] = cntEdge++; edge[cntEdge].v = u; edge[cntEdge].w = w; edge[cntEdge].op = 1; edge[cntEdge].next = head[v]; head[v] = cntEdge++; } int spfa(int s, int n, int dir)//dir == 1反图 { int dis[MAXN], vst[MAXN] = {0}; for(int i = 0; i <= n; i++) dis[i] = inf; queue<int> Q; Q.push(s); vst[s] = 1; dis[s] = 0; while(!Q.empty()) { int pre = Q.front(); Q.pop(); vst[pre] = 0; for(int f = head[pre]; f != -1; f = edge[f].next) { if(dir == 0) { if(edge[f].op == 1) continue; } else { if(edge[f].op == 0) continue; } int son = edge[f].v, w = edge[f].w; if(dis[pre] + w < dis[son]) { dis[son] = dis[pre] + w; if(!vst[son]) { vst[son] = 1; Q.push(son); } } } } int Max = 0; if(!dir) for(int i = 1; i <= n; i++) endDis[i] = dis[i]; else { for(int i = 1; i <= n; i++) { if(endDis[i] + dis[i] > Max) Max = endDis[i] + dis[i]; } } return Max; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m, e; while(scanf("%d %d %d", &n, &m, &e) == 3) { init(n); int u, v, w; for(int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); addEdge(u, v, w); } //正图 spfa(e, n, 0); //反图 int sol; sol = spfa(e, n, 1); printf("%d\n", sol); } return 0; }
普通dijkstra+邻接表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//State: POJ3268 Accepted 3304K 32MS C++ 1971B #include <iostream> #include <queue> using namespace std; const int MAXN = 1005; const int MAXE = 100005; const int inf = 0x3f3f3f3f; typedef struct _node { int v, w; int next; int op; _node(): op(0) {} }N; N edge[2 * MAXE]; int head[MAXN], cntEdge, endDis[MAXN]; void init(int n) { cntEdge = 0; for(int i = 0; i <= n; i++) { head[i] = -1; } } void addEdge(int u, int v, int w) { edge[cntEdge].v = v; edge[cntEdge].w = w; edge[cntEdge].op = 0; edge[cntEdge].next = head[u]; head[u] = cntEdge++; edge[cntEdge].v = u; edge[cntEdge].w = w; edge[cntEdge].op = 1; edge[cntEdge].next = head[v]; head[v] = cntEdge++; } int dijkstra(int s, int n, int dir)//dir == 1反图 { int dis[MAXN], vst[MAXN] = {0}; for(int i = 0; i <= n; i++) dis[i] = inf; dis[s] = 0; for(int i = 0; i < n - 1; i++) { int Min = INT_MAX, index; for(int j = 1; j <= n; j++) { if(dis[j] < Min && !vst[j]) { Min = dis[j]; index = j; } } vst[index] = 1; for(int f = head[index]; f != -1; f = edge[f].next) { if(dir == 0) { if(edge[f].op == 1) continue; } else { if(edge[f].op == 0) continue; } int son = edge[f].v, w = edge[f].w; if(dis[index] + w < dis[son] && !vst[son]) dis[son] = dis[index] + w; } } int Max = 0; if(!dir) for(int i = 1; i <= n; i++) endDis[i] = dis[i]; else { for(int i = 1; i <= n; i++) { if(endDis[i] + dis[i] > Max) Max = endDis[i] + dis[i]; } } return Max; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m, e; while(scanf("%d %d %d", &n, &m, &e) == 3) { init(n); int u, v, w; for(int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); addEdge(u, v, w); } //正图 dijkstra(e, n, 0); //反图 int sol; sol = dijkstra(e, n, 1); printf("%d\n", sol); } return 0; }
优先队列+dijkstra+邻接表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//State: POJ3268 Accepted 3340K 32MS C++ 2238B #include <iostream> #include <queue> #include <functional> #include <vector> using namespace std; const int MAXN = 1005; const int MAXE = 100005; const int inf = 0x3f3f3f3f; typedef struct _node { int v, w; int next; int op; _node(): op(0) {} }N; typedef struct _priNode { int v, dis; //_priNode(): dis(inf) {} _priNode(int a, int b): v(a), dis(b) {} friend bool operator < (const _priNode &n1, const _priNode &n2) { return n1.dis > n2.dis; } }PN; N edge[2 * MAXE]; int head[MAXN], cntEdge, endDis[MAXN]; void init(int n) { cntEdge = 0; for(int i = 0; i <= n; i++) { head[i] = -1; } } void addEdge(int u, int v, int w) { edge[cntEdge].v = v; edge[cntEdge].w = w; edge[cntEdge].op = 0; edge[cntEdge].next = head[u]; head[u] = cntEdge++; edge[cntEdge].v = u; edge[cntEdge].w = w; edge[cntEdge].op = 1; edge[cntEdge].next = head[v]; head[v] = cntEdge++; } int dijkstra(int s, int n, int dir)//dir == 1反图 { int dis[MAXN], vst[MAXN] = {0}; for(int i = 0; i <= n; i++) dis[i] = inf; dis[s] = 0; priority_queue<PN> PQ; PN pre(s, 0); PQ.push(pre); while(!PQ.empty()) { PN pre = PQ.top(); PQ.pop(); vst[pre.v] = 1; for(int f = head[pre.v]; f != -1; f = edge[f].next) { if(dir == 0) { if(edge[f].op == 1) continue; } else { if(edge[f].op == 0) continue; } int son = edge[f].v, w = edge[f].w; if(dis[pre.v] + w < dis[son] && !vst[son]) { dis[son] = dis[pre.v] + w; PN pnSon(son, dis[son]); PQ.push(pnSon); } } } int Max = 0; if(!dir) for(int i = 1; i <= n; i++) endDis[i] = dis[i]; else { for(int i = 1; i <= n; i++) { if(endDis[i] + dis[i] > Max) Max = endDis[i] + dis[i]; } } return Max; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m, e; while(scanf("%d %d %d", &n, &m, &e) == 3) { init(n); int u, v, w; for(int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); addEdge(u, v, w); } //正图 dijkstra(e, n, 0); //反图 int sol; sol = dijkstra(e, n, 1); printf("%d\n", sol); } return 0; }
优化+Bellman_ford+邻接表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <queue> using namespace std; const int MAXN = 1005; const int MAXE = 100005; const int inf = 0x3f3f3f3f; typedef struct _node { int u, v, w; int next; int op; _node(): op(0) {} }N; N edge[2 * MAXE]; int head[MAXN], cntEdge, endDis[MAXN]; void init(int n) { cntEdge = 0; for(int i = 0; i <= n; i++) { head[i] = -1; } } void addEdge(int u, int v, int w) { edge[cntEdge].u = u; edge[cntEdge].v = v; edge[cntEdge].w = w; edge[cntEdge].op = 0; edge[cntEdge].next = head[u]; head[u] = cntEdge++; edge[cntEdge].u = v; edge[cntEdge].v = u; edge[cntEdge].w = w; edge[cntEdge].op = 1; edge[cntEdge].next = head[v]; head[v] = cntEdge++; } int dijkstra(int s, int n, int dir)//dir == 1反图 { int dis[MAXN]; for(int i = 0; i <= n; i++) dis[i] = inf; dis[s] = 0; for(int i = 0; i < n - 1; i++) { bool flag = false; for(int j = 0; j < cntEdge; j++) { if(dir == 0) { if(edge[j].op == 1) continue; } else { if(edge[j].op == 0) continue; } int u = edge[j].u, v = edge[j].v; int w = edge[j].w; if(dis[v] > dis[u] + w) { dis[v] = dis[u] + w; flag = true; } } if(!flag) break; } //判断负环就免了,此题没有 int Max = 0; if(!dir) for(int i = 1; i <= n; i++) endDis[i] = dis[i]; else { for(int i = 1; i <= n; i++) { if(endDis[i] + dis[i] > Max) Max = endDis[i] + dis[i]; } } return Max; } int main(void) { #ifndef ONLINE_JUDGE //freopen("in.txt", "r", stdin); #endif int n, m, e; while(scanf("%d %d %d", &n, &m, &e) == 3) { init(n); int u, v, w; for(int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); addEdge(u, v, w); } //正图 dijkstra(e, n, 0); //反图 int sol; sol = dijkstra(e, n, 1); printf("%d\n", sol); } return 0; }