Problem Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
input
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
output
3
2
floyd
floyd模板直接套上去。
用三角形思想好理解一点。
#include
#include
#include
#include
using namespace std;
long long mp[105][105];
int main()
{
int n,m;
while(cin>>n>>m&&n!=0)
{
memset(mp,0x3f,sizeof mp);//初始化地图的两点间距离都为最大值
for(int i=1;i<=m;i++)
{
int x,y;
long long w;
cin>>x>>y>>w;
mp[x][y]=mp[y][x]=min(mp[x][y],w);//无向图 x->y和y->x都要更新,且保证数据是最小的
}
int st=1,ed=n;
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);//dp思想 松弛操作
}
}
}
cout<<mp[st][ed]<<endl;
}
return 0;
}
dijkstra
dijkstra的思想是广搜+贪心,就是先找到当前点距离起点最近的一个点(这里是贪心思想),然后用这个点去更新与他相连的所有点(广搜),因为每一次都是找当前可以用来更新的点的最小距离,也就是每一次都用到起点最近的点去更新,那么到最后的距离一定是各个点到起点的最短距离。
朴素算法的dijkstra是朴素的寻找最小值
//dijkstra-邻接矩阵+朴素贪心
#include
#include
#include
#include
using namespace std;
long long mp[105][105];
bool vis[105];
long long dis[105];//从该点到起点的最短距离
int main()
{
int n,m;
while(cin>>n>>m&&n!=0)
{
memset(vis,false,sizeof vis);//初始化全部没有访问到
memset(dis,0x3f,sizeof dis);//初始化距离为无穷大(这里0x3f3f3f3f满足两个无穷大相加还是无穷大不会溢出)
memset(mp,0x3f,sizeof mp);
for(int i=1;i<=m;i++)
{
int x,y;
long long w;
cin>>x>>y>>w;
mp[x][y]=mp[y][x]=min(mp[x][y],w);//无向图 x->y和y->x都要更新,且保证数据是最小的
}
int st=1;
int ed=n;
dis[st]=0;
for(int i=1;i<=n;i++)//计数,只要每个点都访问一遍就可以找到最小值
{
/*以下过程在贪心,找到dis数组中距离起点最小的点进行更新*/
long long minn=0x3f3f3f3f,minx;//minn为当前的最小值 minx为当前最小值所对应的点
for(int j=1;j<=n;j++)
{
if(vis[j]==false&&dis[j]<minn)
{
minn=dis[j];
minx=j;
}
}
/*找到了最小的点,利用最小的点搭桥,更新其他的点*/
vis[minx]=true;
for(int j=1;j<=n;j++)
{
if(vis[j]==false)
{
dis[j]=min(dis[j],minn+mp[minx][j]);
}
}
}
cout<<dis[ed]<<endl;//输出终点到起点的距离
}
return 0;
}
因为在贪心寻找最小值的的时候要遍历所有点,那么会带来一个n的时间复杂度,使用优先队列进行优化,可以将n缩小到logn
顺便,实现了一下重载运算符
//dijkstra-邻接矩阵+优先队列优化
#include
#include
#include
#include
#include
using namespace std;
long long mp[105][105];
bool vis[105];
//long long dis[105];
struct NODE{
int x;
long long w;
bool operator < (const NODE &n) const
{
return w<n.w;
}
};
long long dis[105];//从该点到起点的最短距离
priority_queue<NODE> open;
int main()
{
int n,m;
while(cin>>n>>m&&n!=0)
{
memset(vis,false,sizeof vis);//初始化全部没有访问到
memset(dis,0x3f,sizeof dis);//初始化距离为无穷大(这里0x3f3f3f3f满足两个无穷大相加还是无穷大不会溢出)
memset(mp,0x3f,sizeof mp);
for(int i=1;i<=m;i++)
{
int x,y;
long long w;
cin>>x>>y>>w;
mp[x][y]=mp[y][x]=min(mp[x][y],w);//无向图 x->y和y->x都要更新,且保证数据是最小的
}
NODE st;
st.x=1;
st.w=dis[st.x]=0;
open.push(st);
while(!open.empty())
{
NODE noww=open.top();//直接找到当前距离起点最近的点
NODE temp;
open.pop();
if(vis[noww.x]==true)continue;//拿来更新其他店的点不必再进行一次更新
vis[noww.x]=true;
for(int i=1;i<=n;i++)//广搜思想搜索与之相连的点
{
if(dis[i]>dis[noww.x]+mp[noww.x][i])//相连的点是否有必要更新
{
dis[i]=dis[noww.x]+mp[noww.x][i];
vis[i]=false; //已经被更新了最小值,可以重新用他来更新其他店的最小值所以置为未访问
temp.x=i;
temp.w=dis[i];
open.push(temp);
}
}
}
cout<<dis[n]<<endl;
}
return 0;
}