思路:采用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;
}