畅通工程续Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 78589 Accepted Submission(s): 30254 Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
Input 本题目包含多组数据,请处理到文件结束。
Output 对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
Sample Input
3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 2
Sample Output
2 -1
Author linle
Source
Recommend lcy | We have carefully selected several similar problems for you: 2544 2066 2112 1217 1875
|
floyd:经典的多源最短路径算法
#include<bits/stdc++.h>
const int maxn =205;
int m,n;
int edge[maxn][maxn]; //存放图
const int inf=0x3f3f3f3f; //初始化图时为无穷大
void init(){
for(int i=0;i<m;i++){ //根据顶点来化简,不要写错 成边
for(int j=0;j<m;j++){
if(i==j){
edge[i][j]=0;
}else{
edge[i][j]=inf;
}
}
}
}
void floyd(){ //畅通工程常用模板 利用动态规划方程 最短路径要么是此处a->k-b or //a->k-1->b
for(int k=0;k<m;k++){//此处是顶点
for(int j=0;j<m;j++){
for(int i=0;i<m;i++){
if(edge[i][j]>edge[i][k]+edge[k][j]){
edge[i][j]=edge[i][k]+edge[k][j];
}
}
}
}
}
int main(){
while(scanf("%d%d",&m,&n)!=EOF){
init();
int from,to,cost;
for(int i=0;i<n;i++){
scanf("%d%d%d",&from,&to,&cost);
if(from==to){
edge[from][to]=0;
}else{
edge[from][to]=std::min(cost,edge[from][to]);
edge[to][from]=std::min(cost,edge[to][from]);
}
}
int end1,start;
scanf("%d%d",&start,&end1);
// printf("start:%d end1:%d\n",start,end1);
floyd();
// printf("edge[%d][%d]=%d\n",start,end1,edge[start][end1]);
if(edge[start][end1]!=inf)
printf("%d\n",edge[start][end1]);
else
printf("-1\n");
}
return 0;
}
[点击并拖拽以移动]
dijkstra 经典的单源最短路径算法 适合有向图
#include<bits/stdc++.h>
using namespace std;
const int maxsize=205;
const int inf = 0x3f3f3f3f;
int edge[maxsize][maxsize];
int dis[205];
bool visit[205];
int m,n;
void init(){
for(int i=0;i<n;i++){
visit[i]=false;
for(int j=0;j<n;j++){
if(i==j)
edge[i][j]=0;
else{
edge[i][j]=inf;
}
}
}
}
void dijkstra(int u){
for(int i=0;i<n;i++){ //此步可以用找到最小的
dis[i]=edge[u][i];
}
visit[u]=true;
for(int i=1;i<n;i++){
int flag,min1=inf;
for(int j=0;j<n;j++){ //找到离规定点最小的边的顶点,
if(!visit[j]&&dis[j]<min1){
min1=dis[j];
flag=j;//记录顶点下标
}
}
if(min1==inf) return; //搜到的最小点已经是inf说明没有最小的点了
visit[flag]=true;
for(int k=0;k<n;k++){ //进行边松弛 因为有新的最短边被找到
if(dis[flag]+edge[flag][k]<dis[k])
dis[k]=dis[flag]+edge[flag][k];
}
}
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){ //n是顶点数,m是边数
init();
for(int i=0;i<m;i++){
int from,to,cost;
scanf("%d%d%d",&from,&to,&cost);
edge[from][to]=min(cost,edge[from][to]);
edge[to][from]=min(cost,edge[to][from]);
}
int s,e;
scanf("%d%d",&s,&e);
dijkstra(s);
if(dis[e]!=inf)
printf("%d\n",dis[e]);
else
printf("-1\n");
}
return 0;
}
dijkstra 代码化简版 :
#include<bits/stdc++.h>
using namespace std;
const int maxsize=211;
const int inf = 0x3f3f3f3f;
int edge[maxsize][maxsize];
int dis[maxsize];
bool visit[maxsize];
int n,m;
void init(){
for(int i=0;i<n;i++){
dis[i]=inf;
visit[i]=false; //没有初始化
for(int j=0;j<n;j++){
if(i==j)
edge[i][j]=0;
else{
edge[i][j]=inf;
}
}
}
}
/**
3 1 顶点有 3个 边有一条
0 1 1 0->1 权值为1
1 2 判断1->2的最小权值
**/
//典型的单
void dijkstra(int u){
dis[u]=0;
while(1){
int flag,min1=inf;
for(int j=0;j<n;j++){
if(!visit[j]&&dis[j]<min1){
min1=dis[j];
flag=j;
}
}
if(min1==inf) return; //此时表示所有的点到最小的点都是无穷大了1.就是所有的点都已经找到了
//到规定点的距离 2.找到了与规定结点相连的点的最短路径,其余的点与规定的点不想连
visit[flag]=true;
for(int k=0;k<n;k++){
if(dis[flag]+edge[flag][k]<dis[k])
dis[k]=dis[flag]+edge[flag][k];
}
}
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){ //n是顶点数,m是边数
init();
for(int i=0;i<m;i++){
int from,to,cost;
scanf("%d%d%d",&from,&to,&cost);
edge[to][from]=edge[from][to]=min(cost,edge[from][to]);
//edge[to][from]=min(cost,edge[to][from]);
}
int s,e;
scanf("%d%d",&s,&e);
dijkstra(s);
if(dis[e]!=inf)
printf("%d\n",dis[e]);
else
printf("-1\n");
}
return 0;
}