1、poj3255 求次短路
思路:遍历每条边<u, v>, 看begin[u] + dis<u, v> + end[v] 是否为次短路
//求次短路 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> using namespace std; #define clr(x) memset(x,0,sizeof(x)) #define fp1 freopen("poj3255.txt","r",stdin) #define fp2 freopen("out.txt","w",stdout) #define pb push_back #define INF 0x3c3c3c3c const int maxn = 5005; int ss[maxn], tt[maxn]; typedef long long LL; struct Edge {int from,to,dist;}; struct Node { int d,u; bool operator <(const Node &a) const { return a.d<d;//从小到大排序。 } }; int n,m; //点数和边数,用n表示,e不能和m冲突 vector<Edge> edges;//边列表 vector<int> G[maxn];//每个结点出发的边编号(从0开始编号) bool done[maxn];//是否已永久编号 int d[maxn];//s到各个点的距离 int p[maxn];//最短路中的上一条边 void init() { for(int i=0;i<n;i++) G[i].clear();//清空邻接表 edges.clear(); clr(done); } void addedge(int from,int to,int dist) //如果是无向,每条无向边需调用两次addedge { edges.push_back((Edge){from,to,dist}); int temp=edges.size(); G[from].push_back(temp-1); } void dijk(int s) { priority_queue<Node> q; for(int i=0;i<n;i++) d[i]=INF; d[s]=0; memset(done,0,sizeof(done)); q.push((Node){0,s}); while(!q.empty()) { Node x=q.top(); q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for(int i=0;i<G[u].size();i++) { Edge &e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=G[u][i]; q.push((Node){d[e.to],e.to}); } } } } int main() { //fp1; int u, v, w; int T; //scanf("%d", &T); 这地方输入改一下... while(T--) { scanf("%d %d", &n, &m);{ init(); for(int i = 1;i <= m;i++){ scanf("%d %d %d", &u, &v, &w); //printf("%d %d %d\n", u, v, w); u--; v--; addedge(u, v, w); //addedge(v, u, w); } dijk(0); for(int i = 0;i < n;i++) ss[i] = d[i]; int Min1 = INF; edges.clear(); clr(done); dijk(n-1); for(int i = 0;i < n;i++) tt[i] = d[i]; for(int i = 0;i < n;i++){ for(int j = 0;j < G[i].size();j++){ //...存储下来次小边 Edge &e=edges[G[i][j]]; int temp = ss[i] + e.dist + tt[e.to]; //printf("%d~~\n", temp); if(temp>ss[n-1] && temp<Min1){ Min1 = temp; } } } } printf("%d\n", Min1); } return 0; }
2、对于单向边来说(图为单向边),上面(1)那个方法就不适用了。
真正理解Dijkstra ?? ( 感觉还是蛮神的,可以把次短路也按最短路求法那样迭代找出
#include<iostream> using namespace std; #define INF 1000100101 #define maxn 1010 #define maxm 11000 struct Edge{ int v,val,next; }e[maxm]; int box[maxn]; int n,m,S,T; int dis[maxn][2],dp[maxn][2],used[maxn][2]; int dij() { int i,j; memset(used,0,sizeof(used)); memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) dis[i][0]=dis[i][1]=INF; dis[S][0]=0; dp[S][0]=1; for(i=1;i<n*2;i++) { int mn=INF,x,flag; for(j=1;j<=n;j++) { if(!used[j][0] && mn>dis[j][0]) { mn=dis[j][0]; x=j; flag=0; } else if(!used[j][1] && mn>dis[j][1]) { mn=dis[j][1]; x=j; flag=1; } } if(mn==INF) break; used[x][flag]=1; int y,val; for(j=box[x];j!=-1;j=e[j].next) { y=e[j].v; val=e[j].val; if(mn+val<dis[y][0]) { dis[y][1]=dis[y][0]; dp[y][1]=dp[y][0]; dis[y][0]=mn+val; dp[y][0]=dp[x][flag]; } else if(mn+val==dis[y][0]) { dp[y][0]+=dp[x][flag]; } else if(mn+val<dis[y][1]) { dis[y][1]=mn+val; dp[y][1]=dp[x][flag]; } else if(mn+val==dis[y][1]) { dp[y][1]+=dp[x][flag]; } } } if(dis[T][0]+1==dis[T][1]) return dp[T][0]+dp[T][1]; return dp[T][0]; } int main() { int i,j,x,y,val,cas; scanf("%d",&cas); while(cas--) { scanf("%d%d",&n,&m); memset(box,-1,sizeof(box)); for(i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&val); e[i].v=y; e[i].val=val; e[i].next=box[x]; box[x]=i; } scanf("%d%d",&S,&T); printf("%d/n",dij()); } return 0; }
时间: 2024-10-11 06:47:44