#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
//const int N=510,M=100010,INF=0x3f3f3f3f;
//const int N=210,INF=0x3f3f3f3f;
//const int N=100010,INF=0x3f3f3f3f;
const int N=510,M=100010,INF=0x3f3f3f3f;
int n,m,k;
//int h[N],e[N],w[N],ne[N],idx;
//int k,d[N][N];
int g[N][N];
int dist[N],last[N];
bool st[N];
int pre[N];// 记录路径上每个点的前驱节点
vector<int> path;
//typedef pair<int,int> PII;// first 存储距离,second 存储节点编号
/*
struct Edge//bellman_ford
{
int a,b,w;
}e[M];
void add(int a,int b,int c)
{
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
//int p[N];//保存并查集
int prim()//朴素版Prim()算法 求最小生成树 时间复杂度:O(n^2)
{
memset(dist,0x3f,sizeof(dist));
dist[1]=0;
int res=0;
for(int i=0;i<n;i++) // 一共要加 n 个点
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!st[j]&&(t==-1||dist[j]<dist[t]))
t=j;
}
if(dist[t]==INF) return INF;
st[t]=true;
res+=dist[t];
for(int j=1;j<=n;j++)//更新其他点的距离
{
if(!st[j])
dist[j]=min(dist[j],g[t][j]);
}
}
return res;
}
int main()//朴素版Prim()算法 时间复杂度:O(n^2)
{
memset(g,0x3f,sizeof g);
cin>>n>>m;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=g[b][a]=min(g[a][b],c);
}
int res=prim();
if(res==INF)puts("impossible");
else cout<<res<<endl;
return 0;
}
struct Edge//Kruskal算法 求最小生成树 时间复杂度:O(mlogm)
{
int a,b,w;
bool operator < (const Edge &W)const//通过边长进行排序,
{
return w < W.w;
}
}edges[M];
int find(int x)//Kruskal算法 求最小生成树 时间复杂度:O(mlogm)
{
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
int res=0,cnt=0;
void kruskal()//Kruskal算法 求最小生成树 时间复杂度:O(mlogm)
{
sort(edges,edges+m);
for(int i=1;i<=n;i++)p[i]=i;
for(int i=0;i<m;i++)//依次尝试加入每条边
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=find(a),b=find(b);
if(a!=b)
{
p[a]=b;
res+=w;
cnt++;
}
}
}
int main()//Kruskal算法 求最小生成树 时间复杂度:O(mlogm)
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b,w;
cin>>a>>b>>w;
edges[i]={a,b,w};
}
kruskal();
if(cnt<n-1)puts("impossible");
else cout<<res;
return 0;
}
void floyd()//floyd多源求最短路
{
for(int k=1;k<=n;k++) // 对中间顶点k从1遍历到
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
int main()//floyd求最短路
{
memset(d,0x3f,sizeof d);
cin>>n>>m>>k;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
d[a][b]=min(d[a][b],c);
}
for(int i=1;i<=n;i++)d[i][i]=0;
floyd();
while(k--)
{
int a,b;
cin>>a>>b;
if(d[a][b]>INF/2)puts("impossible");
else cout<<d[a][b]<<endl;
}
return 0;
}
int dijkstra()//朴素版dijkstra 求1到n的最短距离,稠密图使用邻接矩阵存储
{
memset(dist,INF,sizeof dist);
dist[1]=0;
for(int i=1;i<=n;i++)//循环n次
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!st[j]&&(t==-1||dist[t]>dist[j]))//找出距离最小点
t=j;
}
st[t]=true;
//用t更新其他点的距离
for(int j=1;j<=n;j++)
dist[j]=min(dist[j],g[t][j]);
}
return dist[n]==INF? -1:dist[n];
}
int main()//朴素版dijkstra 求1到n的最短距离
{
memset(g,INF,sizeof g);
cin>>n>>m;
for(int i=0;i<n;i++)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c);
}
cout<<dijkstra()<<endl;
return 0;
}
int dijkstra()//堆优化版dijkstra
{
memset(dist, INF, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap; // 小顶堆
heap.push({0, 1}); // first 存储距离,second 存储节点编号
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver] ; i != -1 ; i = ne[i])
{
int j = e[i];
if (distance + w[i] < dist[j])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
return dist[n]==INF? -1:dist[n];
}
int main()//堆优化版dijkstra
{
memset(h,-1,sizeof h);
cin>>n>>m;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
cout<<dijkstra()<<endl;
return 0;
}
*/
void dijkstra(int start,int end)//更改dijkstra 求起点到终点的path数组
{
memset(dist,0x3f,sizeof dist);
dist[start]=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
if(!st[j]&&(t=-1||dist[t]>dist[j]))
t=j;
st[t]=true;
for(int j=1;j<=n;j++)
if(dist[j]>dist[t]+g[t][j])
{
dist[j]=dist[t]+g[t][j];
pre[j]=t;
}
}
printf("dist[%d]= %d\n",end,dist[end]);// 输出起点到终点的最短距离
for(int i=end;i!=start;i=pre[i])// 根据前驱节点数组获取路径转移至path数组中此时最短路为逆序
path.push_back(i);
path.push_back(start);
//路径逆序输出 (此时转为正序)
for(int i=path.size()-1;i>=0;i--)
cout<<path[i]<<' ';
cout<<endl;
}
int main()
{
memset(g,0x3f,sizeof g);
cin>>n>>m;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c);
}
int start,end;
cin>>start>>end;
dijkstra(start,end);
return 0;
}
/*
void bellman_ford()//有边数限制的最短路(Bellman-Ford)
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
printf("初始状态:\n");
for(int i=1;i<=n;i++)
printf("dist[%d]= %d\n",i,dist[i]);
puts("-------------------------");
for(int i=1;i<=k;i++)//k为有限边最短路有限边边数 则需迭代k次
{
memcpy(last,dist,sizeof dist);//将上一次迭代值复制给last
for(int j=0;j<m;j++)//枚举每条边
{
dist[e[j].b]=min(dist[e[j].b],last[e[j].a]+e[j].w);
}
printf("第%d次迭代的结果:\n",i);
for(int i=1;i<=n;i++)//枚举k次迭代后1到其余点的最短距离
printf("dist[%d]= %d\n",i,dist[i]);
puts("-----------------------------");
}
}
int main()//有边数限制的最短路(Bellman-Ford)
{
cin>>n>>m>>k;
for(int i=0;i<m;i++)
cin>>e[i].a>>e[i].b>>e[i].w;
bellman_ford();
if(dist[n]>INF/2)puts("impossible");
else cout<<dist[n]<<endl;
return 0;
}
*/