题:总结
可能第一次接触到这个算法不知道算法是怎么来的,但是当遇到题的时候代进去数想一遍怎么运行,多思考。我在网上看到的一句话来形容这个算法:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径。
先说2387,一道非常经典、非常水的一道Dijkstra题,在题目中真知灼见。
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
#define M 1010
int map[M][M];
int visit[M],low[M];
void Dijkstra(int n)
{
int pos,min;
for(int i = 1;i <= n; i++){ //初始化,以第一个点当做原点
low[i] = map[1][i];
visit[i] = 0;
}
for(int i = 1;i <= n; i++){
min = INF;
for(int j = 1;j <= n; j++)
if(!visit[j] && min > low[j]){ //找没有标记的点
min = low[j];
pos = j; //记录它,准备遍历
}
visit[pos] = 1;
for(int j = 1;j <= n; j++)
if(!visit[j] && low[j] > low[pos] + map[pos][j]) //松弛,对应总结中的那句话
low[j] = low[pos] + map[pos][j];
}
}
int main()
{
int t,n;
scanf("%d%d",&t,&n);
for(int i = 1;i <= n; i++)
for(int j = 1;j <= n; j++) //初始化,最开始都是无穷远,
map[i][j] = INF; //也可以加上自己到自己的距离为零
int c1,c2,distance;
for(int i = 1;i <= t; i++){
scanf("%d%d%d",&c1,&c2,&distance);
if(map[c1][c2] > distance)
map[c1][c2] = map[c2][c1] = distance;
}
/*
for(int i = 1;i <= n; i++){
for(int j = 1;j <= n; j++)
printf("%d ",map[i][j]);
printf("\n");
}
*/
Dijkstra(n);
printf("%d\n",low[n]);
return 0;
}
这道题用spfa,节约了空间,但是没节约时间。
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#include<cstdio>
#define inf 0x3f3f3f3f
using namespace std;
class Node
{
public:
int e,v;
Node(int a,int b){e = a,v = b;}
};
vector<Node>s[1005];
int t,n;
int dis[1005],visit[1005];
void spfa()
{
memset(visit,0,sizeof(visit));
memset(dis,inf,sizeof(dis));
queue<int>Q;
Q.push(1);
visit[1] = true;
dis[1] = 0;
while(!Q.empty()){
int u = Q.front();
Q.pop();
visit[u] = false;
int num = s[u].size();
for(int i = 0;i < num; i++){
if(dis[s[u][i].e] < dis[u] + s[u][i].v)
continue;
dis[s[u][i].e] = dis[u] + s[u][i].v;
if(!visit[s[u][i].e]){
visit[s[u][i].e] = true;
Q.push(s[u][i].e);
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
cin>>t>>n;
for(int i = 1;i <= n; i++)
s[i].clear();
int a,b,c;
for(int i = 1;i <= t; i++){
cin>>a>>b>>c;
s[a].push_back(Node(b,c));
s[b].push_back(Node(a,c));
}
spfa();
cout<<dis[n]<<endl;
return 0;
}
#include<iostream>
#include<cstdio>
using namespace std;
#define M 1010
#define INF 0x3f3f3f3f
int map[M][M],d[M],visit[M];
void Dijkstra(int n)
{
for(int i =1;i <= n; i++){
visit[i] = 0;
d[i] = map[1][i]; //d不代表从1到n的最短路径,而是最大承载量
}
int pos;
for(int i = 1;i <= n; i++){
int f = -1;
for(int j = 1;j <= n; j++)
if(!visit[j] && d[j] > f){
f = d[j];
pos = j;
}
visit[pos] = 1;
for(int j = 1;j <= n; j++){
if(!visit[j] && d[j] < min(d[pos],map[pos][j])) //取小的是根据题最大载重
d[j] = min(d[pos],map[pos][j]);
}
}
}
int main()
{
int nCase;
scanf("%d",&nCase);
for(int k = 1;k <= nCase; k++){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; i++)
for(int j = 1;j <= n; j++)
map[i][j] = 0; //求最大当然初始化为小,此题不是求最短路径
for(int i = 1;i <= m; i++){
int c1,c2,weight;
scanf("%d%d%d",&c1,&c2,&weight);
map[c1][c2] =map[c2][c1] = weight;
}
Dijkstra(n);
printf("Scenario #%d:\n%d\n\n",k,d[n]);
}
return 0;
}
POJ2253
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
#define M 210
double map[M][M],d[M],coor[M][M];
int visit[M];
double Distance(int i,int j)
{
double a = coor[i][0] - coor[j][0];
double b = coor[i][1] - coor[j][1];
return sqrt(a*a + b*b);
}
void Dijkstra(int n)
{
int pos,m;
for(int i = 1;i <= n; i++){
visit[i] = 0;
d[i] = map[1][i];
}
pos = 1;
d[1] = 0;
visit [1] = 1 ;
for(int i = 1;i < n; i++){
m = INF;
for(int j = 1;j <= n; j++)
if(!visit[j] && m > d[j]){
m = d[j]; //一定不能把错误留在这里
pos = j;
}
visit[pos] = 1;
for(int j = 1;j <= n; j++){
double maxn = d[pos] > map[pos][j] ? d[pos]:map[pos][j]; //判断最大
d[j] = d[j] < maxn ? d[j]:maxn; //最大中的最小
}
}
}
int main()
{
int n,nCase = 1;
while(scanf("%d",&n),n){
for(int i = 1;i <= n; i++)
for(int j = 1;j <= n; j++)
map[i][j] = INF;
for(int i = 1;i <= n; i++)
scanf("%lf%lf",&coor[i][0],&coor[i][1]);
for(int i = 1;i <= n; i++)
for(int j = 1;j <= n; j++)
map[i][j] = Distance(i,j);
Dijkstra(n);
printf("Scenario #%d\nFrog Distance = %.3f\n\n",nCase++,d[2]);
}
return 0;
}