问题描述
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。
输入格式
第一行两个整数n, m。
接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。
输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
输入样例
3 3
1 2 -1
2 3 -1
3 1 2
输出样例
-1
-2
解题思路
不断循环可走路径,计算从s到任意一点的最短距离。当某次循环中没有更新最短路径,说明此时已经达到最佳效果。同样当循环次数达到顶点数(n)时,说明存在负圈。参考链接
解题代码
#include<iostream>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
struct node
{
int from,to,cost;
};
node edge[200010];
//表示点N到i点的最短距离
int d[20005];
//如果存在最短路径,返回true,否则为存在负圈
bool shortway(int s)
{
memset(d,INF,sizeof(d));
d[s]=0;
int j=0;
while(true)
{
bool update=false;
for(int i=0;i<m;i++)
{
node ee=edge[i];
//当这条边的起点在路线中,并且走这条路更短一些时
if(d[ee.from]!=INF&&d[ee.to]>d[ee.from]+ee.cost)
{
d[ee.to]=d[ee.from]+ee.cost;
update=true;
}
}
j++;
//不再更新,说明已经全部为最短路
if(!update) return true;
//当循环次数等于顶点数时,说明有负圈
if(j==n) return false;
}
}
int main()
{
//n个顶点,m条边
cin>>n>>m;
int u,v,l;
//可走路线存入edge,当是双向路线时,存入两次
for(int i=0;i<m;i++)
{
cin>>u>>v>>l;
edge[i].from=u-1;
edge[i].to=v-1;
edge[i].cost=l;
//edge[i+m].from=u-1;
//edge[i+m].to=v-1;
//edge[i+m].cost=l;
}
if(shortway(0))
{
for(int i=1;i<n;i++)
cout<<d[i]<<endl;
}
return 0;
}
最短路模板应用(试题 算法提高 道路和航路):
问题描述
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
农夫约翰正在针对一个新区域的牛奶配送合同进行研究。他打算分发牛奶到T个城镇(标号为1…T),这些城镇通过R条标号为(1…R)的道路和P条标号为(1…P)的航路相连。
每一条公路i或者航路i表示成连接城镇Ai(1<=A_i<=T)和Bi(1<=Bi<=T)代价为Ci。每一条公路,Ci的范围为0<=Ci<=10,000;由于奇怪的运营策略,每一条航路的Ci可能为负的,也就是-10,000<=Ci<=10,000。
每一条公路都是双向的,正向和反向的花费是一样的,都是非负的。
每一条航路都根据输入的Ai和Bi进行从Ai->Bi的单向通行。实际上,如果现在有一条航路是从Ai到Bi的话,那么意味着肯定没有通行方案从Bi回到Ai。
农夫约翰想把他那优良的牛奶从配送中心送到各个城镇,当然希望代价越小越好,你可以帮助他嘛?配送中心位于城镇S中(1<=S<=T)。
输入格式
输入的第一行包含四个用空格隔开的整数T,R,P,S。
接下来R行,描述公路信息,每行包含三个整数,分别表示Ai,Bi和Ci。
接下来P行,描述航路信息,每行包含三个整数,分别表示Ai,Bi和Ci。
输出格式
输出T行,分别表示从城镇S到每个城市的最小花费,如果到不了的话输出NO PATH。
输入样例
6 3 3 4
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10
输出样例
NO PATH
NO PATH
5
0
-95
-100
解题思路
简化题目:有t个顶点,有r条双向路径,p条单向路径,即共有2*r+p条路径。求顶点s到各顶点的最短路径。
解题结果:有两个测试点超时,得分90。
解题代码
#include<iostream>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
//t个城镇,r条公路,p条航道,中心在s
//公路双向,航道单向
int t,r,p,s;
struct edge
{
int from,to,cost;
} ;
edge ee[150010];
//从中心s出发到各城镇的最短路
int d[25010];
bool shortway(int s)
{
memset(d,INF,sizeof(d));
d[s]=0;
int j=0;
while(true)
{
bool update=false;
for(int i=0;i<2*r+p;i++)
{
edge temp=ee[i];
if(d[temp.from]!=INF&&d[temp.to]>d[temp.from]+temp.cost)
{
d[temp.to]=d[temp.from]+temp.cost;
update=true;
}
}
j++;
if(!update) return true;
if(j==t) return false;
}
}
int main()
{
cin>>t>>r>>p>>s;
int ai,bi,ci;
for(int i=0;i<r;i++)
{
cin>>ai>>bi>>ci;
ee[i].from=ai-1;
ee[i].to=bi-1;
ee[i].cost=ci;
ee[i+r].from=bi-1;
ee[i+r].to=ai-1;
ee[i+r].cost=ci;
}
for(int i=0;i<p;i++)
{
cin>>ai>>bi>>ci;
ee[2*r+i].from=ai-1;
ee[2*r+i].to=bi-1;
ee[2*r+i].cost=ci;
}
if(shortway(s-1)) cout<<"Y"<<endl;
for(int i=0;i<t;i++)
{
if(d[i]!=INF) cout<<d[i]<<endl;
else cout<<"NO PATH"<<endl;
}
return 0;
}