上周学了Bellman-Ford算法始终不能理解其本质,一次看了一篇大神的博客,瞬间茅塞顿开。原来Bellman-Ford算法与离散数学有关!
例题:
最短路
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 83956 Accepted Submission(s): 36323
Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input 输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output 对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input
2 11 2 33 31 2 52 3 53 1 20 0
Sample Output
32
#include <cstdio>
using namespace std;
const int MAX_E = 10002;
const int MAX_V = 102;
const int INF = 0x3f3f3f3f;
struct node{ // 存边及其两个端点
int from;
int to;
int cost;
}es[MAX_E];
int V,E;
int d[MAX_V];
void bellman(int s){
for(int i=0;i<MAX_V;i++){
d[i]=INF;
}
d[s]=0;
//V-1
bool update;
for(int i=0;i<V-1;i++){ // 这是关键,为什么是会是v-1,这需要用到离散数学的知识
update=false; // 注意观察,第一次循环是起点到长度为1的点的最短距离,第二次是起点到长度为2的点的最短距离.....
for(int j=0;j<2*E;j++){ // 一个有V个点的图,则形成的无环的最大长度为多少,没错就是V-1
if(d[es[j].from]!=INF && d[es[j].to] > d[es[j].from]+es[j].cost){
d[es[j].to]=d[es[j].from]+es[j].cost;
update=true;
}
}
if(!update){
break;
}
}
}
int main(){
while(~scanf("%d%d",&V,&E),(V||E)){
for(int i=0;i<E;i++){
scanf("%d%d%d",&es[i].from,&es[i].to,&es[i].cost);
es[i+E].to=es[i].from;
es[i+E].from=es[i].to;
es[i+E].cost=es[i].cost;
}
bellman(1);
printf("%d\n",d[V]);
}
return 0;
}
结合学过的其他知识很重要!之前说过V-1是无环图的,如果遍历超过V-1次就说明图是有环的(这个可以判断图是否有环)。