演算法作業 (最短路+記錄全部路徑)
阿新 • • 發佈:2018-11-08
思路:採用n*logn的優化迪傑斯特拉演算法,求出最短路,反向建圖以後,在dfs搜尋即可,用set+vector記錄路徑,注意vector的傳遞需要加引用(用string 就不用加引用)。
實現非常簡單,直接看程式碼就行。
#include <bits/stdc++.h> using namespace std; const int maxn=100; typedef long long ll; struct Edge { int u,v,w,next; }edge[maxn<<1],edge2[maxn<<1]; int head[maxn]; int num; void addEdge(int u,int v,int w) { edge[num].u=u; edge[num].v=v; edge[num].w=w; edge[num].next=head[u]; head[u]=num++; } int num2,head2[maxn]; void addEdge2(int u,int v,int w) { edge2[num2].u=u; edge2[num2].v=v; edge2[num2].w=w; edge2[num2].next=head2[u]; head2[u]=num2++; } void init() { memset(head,-1,sizeof(head)); memset(head2,-1,sizeof(head2)); num2=0; num=0; } struct node { int num, val; //存編號 和距離 node(int _num=0, int _val=0):num(_num), val(_val) {} bool operator <(const node &tmp) const { return val > tmp.val; } node()=default; }; int n,s,t; bool vis[maxn]; int dis[maxn]; int path[maxn]; void dijkstra(int st) //起點 { priority_queue<node> que; memset(dis, 0x3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); dis[st] = 0; que.push(node(st, 0)); while(!que.empty()) { node p = que.top(); que.pop(); int nown = p.num; if(vis[nown]) continue; vis[nown] = true; for(int i=head[nown]; i!=-1; i=edge[i].next) { Edge e = edge[i]; if(dis[e.v] > dis[nown] + e.w && !vis[e.v]) { dis[e.v] = dis[nown] + e.w; que.push(node(e.v,dis[e.v])); } } } } set<vector<int>> se; void prinPath(int s,vector<int> &vec) { vec.push_back(s); if(s==::s) { reverse(vec.begin(),vec.end()); se.insert(vec); vec.clear(); vec.push_back(::t); return; } for(int i=head2[s];i!=-1;i=edge2[i].next) { int v=edge2[i].v,w=edge2[i].w; if(dis[v]==dis[s]-w) { //printf("%d...%d\n",v,s); prinPath(v,vec); //return; } } // reverse(vec.begin(),vec.end()); // se.insert(vec); } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int Case=0; while(scanf("%d",&n)!=EOF) { se.clear(); init(); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int w; scanf("%d",&w); if(w==-1) continue; addEdge(i,j,w); addEdge2(j,i,w); } } scanf("%d%d",&s,&t); dijkstra(s); printf("Case %d\n",++Case); printf("The least distance from %d -> %d is %d\n",s,t,dis[t]); vector<int> vec; prinPath(t,vec); set<vector<int> >::iterator it; printf("最短路徑有:%d 條\n",se.size()); printf("the path is "); for(it=se.begin();it!=se.end();it++){ vector<int> ans=*it; for(int i=0;i<ans.size()-1;i++) { printf("%d->",ans[i]); } printf("%d\n",ans[ans.size()-1]); cout<<endl; } } return 0; }