求一个图最短路边的办法。好像下面的那个有问题。单向边和双向边一定是有区别的。这个比较容易。参照该文的最短路网络流题目和连通图题目一题求最短路关节边
另外上述2个题目的代码好像有问题。
在UVALIVE 6885中不能得到AC。不知道原因。感觉是对的。
另一种判断最短路的方法就是
从起点到u+从终点到v+边U,V权值==最短路值那么这条边为最短路
这种方案的代码
for (int i = 1 ; i <= M ; i++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); u[i]++;v[i]++; S.add_edge(u[i],v[i],w[i],i); S.add_edge(v[i],u[i],w[i],i); T.add_edge(u[i],v[i],w[i],i); T.add_edge(v[i],u[i],w[i],i); } S.dijkstra(source); T.dijkstra(target); long long ans = 0; for (int i = 1 ; i <= P ; i++) { for (int j = S.head[i] ; j != -1 ; j = S.edge[j].next) { int v = S.edge[j].v; if (S.dis[i] + T.dis[v] + S.edge[j].w == S.dis[target]) //这条边为最短路边 } }
同时另一种可能存在问题的方法如下
for (int i = 1 ; i <= m ; i++) { scanf("%d%d%I64d",&u[i],&v[i],&w[i]); S.add_edge(u[i],v[i],w[i],i); S.add_edge(v[i],u[i],w[i],i); T.add_edge(u[i],v[i],w[i],i); T.add_edge(v[i],u[i],w[i],i); } S.dijkstra(s); T.dijkstra(t); init(); for (int i = 1 ; i <= m ; i++) { int tu = u[i]; int tv = v[i]; LL tw = w[i]; if ((S.dis[tu] + tw == S.dis[tv] && T.dis[tv] + tw == T.dis[tu]) ||(S.dis[tv] + tw == S.dis[tu] && T.dis[tu] + tw == T.dis[tv])) { add_edge(tu,tv,tw,i); add_edge(tv,tu,tw,i);//这里是为了处理tarjan无向图 其实就是u[i],v[i],w[i]这条边为最短路边。 } } slove(n);
对于上述方案的有向图 建图有区别
如下
for (int i = 0 ; i < M ; i++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); St.add_edge(u[i],v[i],w[i],i + 1); //St.add_edge(v[i],u[i],w[i],i + 1); //Ted.add_edge(u[i],v[i],w[i],i + 1); Ted.add_edge(v[i],u[i],w[i],i + 1); } scanf("%d%d",&A,&B); St.dijkstra(A); /* if (St.dis[B] == INF) { puts("0"); continue; } */ Ted.dijkstra(B); for (int i = 0 ; i < M ; i++) { int tu = u[i]; int tv = v[i]; int tw = w[i]; if (tu == tv) continue; if ((St.dis[tu] + tw == St.dis[tv] && Ted.dis[tv] + tw == Ted.dis[tu]) ||(St.dis[tv] + tw == St.dis[tu] && Ted.dis[tu] + tw == Ted.dis[tv])) { add_edge(tu,tv,1);//这里添加的是网络流的边无需双向 } }
POJ 2387 Til the Cows Come Home
直接求最短路末班题。我这里是dijkstra+优先队列优化的班
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 4100; const int MAXM = 40005; const int INF = 0x3f3f3f3f; struct Edge { int u,v,next; int w; }edge[MAXM]; int head[MAXN],tot; void init() { tot = 0; memset(head,-1,sizeof(head)); } void add_edge(int u,int v,int w) { edge[tot].u = u; edge[tot].v = v; edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot++; } struct heapnode { int val,u; bool operator < (const heapnode &rhs) const { return val > rhs.val; } }; bool done[MAXN]; int dis[MAXN]; priority_queue<heapnode>q; int N,M; void dijkstra(int s) { memset(done,false,sizeof(done)); while (!q.empty()) q.pop(); memset(dis,0x3f,sizeof(dis)); dis[s] = 0; q.push((heapnode){dis[s],s}); while (!q.empty()) { heapnode x = q.top(); q.pop(); int u = x.u; if (done[u]) continue; done[u] = true; for (int i = head[u] ; i != -1 ; i = edge[i].next) { int v = edge[i].v; if (dis[v] > dis[u] + edge[i].w) { dis[v] = dis[u] + edge[i].w; q.push((heapnode){dis[v],v}); } } } } int main() { while (scanf("%d%d",&N,&M) != EOF) { swap(N,M); init(); for (int i = 0 ; i < M ; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } dijkstra(1); printf("%d\n",dis[N]); } return 0; }