【题目】
1624: 最短路
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 241 Solved: 60
[Submit][Status][Web Board]
Description
有n个城市编号为1—n,m条路,告诉你每条路的长度,求给定两点的最短路径长度。
Input
T 组数据
每组数据第一行有两个正整数n,m(n<=1000,m<=10000)分别表示城市的数量和路的条数,接下来m行,每行3个整数a,b,c,表示城市a和城市b之间有一条c长度的路
最后一行输入两个整数x,y。
Output
输出城市 x 到城市 y 的最短路径。如果不存在输出-1。
Sample Input
2
3 2
1 2 2
2 3 3
1 3
4 2
1 2 3
1 3 2
1 4
Sample Output
5
-1
【题解】
用并查集判断是否连通,用dijkstra算法优化最短路径
dijkstra算法:
(注意该算法要求图中不存在负权边)
对于与a相连的所有点b,若dis[a]+cost[a][b]比当前的dis[b]小,则更新dis[b]
注意初始化时dis[]和cost[][]赋极大值
板子:
const int inf=0x3f3f3f3f;
int cost[105][105]; //用于储存点与点之间的距离
void dijkstra(int a) //求出点a到所有点的最短距离
{
int i,vis[105];
for(i=1;i<=n;i++) //初始化dis[],vis[]
{
dis[i]=inf;
vis[i]=0;
}
dis[a]=0; //显然点到自身距离为0
while(1)
{
int v=-1;
for(i=1;i<=n;i++)
if(!vis[i]&&(v==-1||dis[i]<dis[v]))
v=i;
if(v==-1) //所有路径均已标记完毕
break;
vis[v]=1; //标记
for(i=1;i<=n;i++)
dis[i]=min(dis[i],dis[v]+cost[v][i]); //更新dis[]
}
}
【代码】
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int cost[1005][1005];
int dis[1005],n,m;
int pre[1005];
int t,i,a,b,c,x,y;
int find(int x)
{
int r=x;
while(pre[r]!=r)
r=pre[r];
int i=x,j;
while(pre[i]!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
int join(int x,int y)
{
x=find(x),y=find(y);
if(x!=y)
{
pre[x]=y;
return 0;
}
return 1;
}
void dijkstra(int a)
{
int vis[1005],v;
for(i=1;i<=n;i++)
{
dis[i]=inf;
vis[i]=0;
}
dis[a]=0;
while(1)
{
int v=-1;
for(i=1;i<=n;i++)
if(!vis[i]&&(v==-1||dis[i]<dis[v]))
v=i;
if(v==-1) break;
vis[v]=1;
for(i=1;i<=n;i++)
dis[i]=min(dis[i],dis[v]+cost[v][i]);
}
}
void init()
{
memset(cost,inf,sizeof(cost));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
pre[i]=i;
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
join(a,b);
cost[a][b]=min(cost[a][b],c);
cost[b][a]=min(cost[a][b],c);
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&x,&y);
if(!join(x,y))
printf("-1\n");
else
{
dijkstra(x);
printf("%d\n",dis[y]);
}
}
return 0;
}
【不知道说的什么鬼】
久违了久违了,接下来也要持续学习+更新
考一门丢一门hhh,丢掉高数,丢掉包袱