暢通工程續
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 37269 Accepted Submission(s): 13759
現在,已知起點和終點,請你計算出要從起點到終點,最短需要行走多少距離。
每組數據第一行包含兩個正整數N和M(0<N<200,0<M<1000),分別代表現有城鎮的數目和已修建的道路的數目。城鎮分別以0~N-1編號。
接下來是M行道路信息。每一行有三個整數A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城鎮A和城鎮B之間有一條長度爲X的雙向道路。
再接下一行有兩個整數S,T(0<=S,T<N),分別代表起點和終點。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define size 205
#define INF 0x7fffffff//16進制
int g[size][size];//鄰接矩陣 存儲圖
bool vis[size];//標記函數
int dis[size];//記錄最短路徑
int n,m;//n表示點的數量 m表示邊的數量
void init()
{
for(int i=0;i<n;i++)//初始化整個圖
for(int j=0;j<n;j++)
if(i==j)//自身與自身的距離爲0
g[i][j]=0;
else
g[i][j]=INF;
}
void Dijkstra(int s,int e)//s起點 e終點 點s 到 點e的最短路徑
{
for(int i=0;i<n;i++)//初始化,開始時最短路徑dis[]爲INF,vis[]爲false
{
dis[i]=g[s][i];
vis[i]=false;
}
dis[s]=0;//將起始點s的最短路徑的距離記錄爲0
vis[s]=true;//並且標記訪問到的當前點(s);
for(int i=0;i<n;i++)//查找最短路徑
{
int minnum=INF;
int temp=s;
for(int j=0;j<n;j++)
if(!vis[j]&&dis[j]<minnum)//尋找一個最短距離,並且記錄該點的信息
{
temp=j;
minnum=dis[j];
}
if(minnum==INF)//如果當前的最短距離仍爲INF表示此次訪問無效 PS這裏可有可無 均能AC
break ;
vis[temp]=true;//訪問一次,標記一次
for(int j=0;j<n;j++)
if(!vis[j]&&g[temp][j]<INF&&dis[temp]+g[temp][j]<dis[j])//對於每個與點temp相鄰接的點j,均訪問一次,並且更新最短路徑
dis[j]=dis[temp]+g[temp][j];
}
if(dis[e]==INF)//如果到達終點時最短路徑仍爲INF表示無最短路徑,反之則有
printf("-1\n");
else
printf("%d\n",dis[e]);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();//
for(int i=0;i<m;i++)
{
int a,b,x;
scanf("%d%d%d",&a,&b,&x);
if(x<g[a][b])//注意,此處需將原來初始化的(a,b,INF)改爲(a,b,c);
g[a][b]=g[b][a]=x;
}
int s,t;
scanf("%d%d",&s,&t);
Dijkstra(s,t);
}
return 0;
}
代碼二[Floyd]#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define INF 0xfffffff
#define size 205
int g[size][size];
int n,m;
void Init()
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i==j)//自身與自身的距離爲0
g[i][j]=0;
else
g[i][j]=INF;
}
void Floyd(){
int i,j,k;
for(k=0;k<n;k++)
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(g[i][j]>g[i][k]+g[k][j])
g[i][j]=g[i][k]+g[k][j];
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
Init();
for(int i=0;i<m;i++)
{
int a,b,x;
scanf("%d%d%d",&a,&b,&x);
if(x<g[a][b])
g[a][b]=g[b][a]=x;
}
int s,t;
scanf("%d%d",&s,&t);
Floyd();
if(g[s][t]==INF)
printf("-1\n");
else
printf("%d\n",g[s][t]);
}
return 0;
}
代碼三[SPFA 思路與Dijkstra 很相似]
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
#define INF 0xfffffff
#define size 205
int g[size][size];
int dis[size];
bool vis[size];
int n,m;
void Init()
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i==j)
g[i][j]=0;
else
g[i][j]=INF;
}
int SPFA(int s,int e)
{
for(int i=0;i<n;i++)
{
dis[i]=INF;
vis[i]=false;
}
queue<int> Q;
while(!Q.empty())
Q.pop();
dis[s]=0;
vis[s]=true;
Q.push(s);
int temp=0;
while(!Q.empty())
{
temp=Q.front();
Q.pop();
if(dis[temp]==INF)
break;
vis[temp]=false;
for(int i=0;i<n;i++)
if(dis[i]>dis[temp]+g[temp][i])//注意此處與Dijkstra有點不同
{
dis[i]=dis[temp]+g[temp][i];
if(!vis[i])//在此處進行檢驗
{
vis[i]=true;
Q.push(i);
}
}
}
if(dis[e]==INF)
printf("-1\n");
else
printf("%d\n",dis[e]);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
Init();
for(int i=0;i<m;i++)
{
int a,b,x;
scanf("%d%d%d",&a,&b,&x);
if(x<g[a][b])
g[a][b]=g[b][a]=x;
}
int s,t;
scanf("%d%d",&s,&t);
SPFA(s,t);
}
return 0;
}
代碼四[你會發現Dijkstra從這上面經過,貌似在嚴蔚敏的數據結構見過哦]
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define INF 0xfffffff
#define size 205
int dis[size];
int n,m,cnt;
struct node
{
int u,v;
int w;
}edge[1005*2];//注意此處
void addedge(int u,int v,int w)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].w=w;
cnt++;
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].w=w;
cnt++;
}
void Bellman_Ford(int s,int e)
{
for(int i=0;i<n;i++)
dis[i]=INF;
dis[s]=0;
for(int k=0;k<n;k++)
for(int i=0;i<cnt;i++)
if(dis[edge[i].u]!=INF && dis[edge[i].v]>dis[edge[i].u]+edge[i].w)
dis[edge[i].v]=dis[edge[i].u]+edge[i].w;
if(dis[e]==INF)
printf("-1\n");
else
printf("%d\n",dis[e]);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
cnt=0;
for(int i=0;i<m;i++)
{
int a,b,x;
scanf("%d%d%d",&a,&b,&x);
addedge(a,b,x);
}
int s,t;
scanf("%d%d",&s,&t);
Bellman_Ford(s,t);
}
return 0;
}
Bellmen_Ford算法的運算時間爲O(nm)適合n^2>m的稀疏圖
當遇到n^2<m的稠密圖時最好用Dijkstra算法,其運算時間爲O(n^2)。