图论的经典入门题目:

         一开始想用此题试试Mellman_ford算法,可是不料,直接TLE

        最后改为SPFA,就过了,看来Mellman_ford算法不经优化,还是行不通的。。

不够至少通过这道题目认识了Mellman_ford算法:

Mellman_ford算法流程:

 

给定图G(V, E)(其中V、E分别为图G的顶点集与边集),源点s,

数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]为, Distant[s]为0; 
以下操作循环执行至多n-1次,n为顶点数:
对于每一条边e(u, v),如果Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值;
若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。

 

ps:

1、单向还是双向图,考虑清楚
2、注意那个maxInt这个值超不超,够不够
3、注意是否两点间有多条路径
4、分清变量是double型的还是int型的
5、注意主函数中初始化map[][]中的点边不要搞错(注意所有初始化,正确命名好变量)

 

TEL代码(Mellman_ford算法):

#include<iostream> 
using namespace std; 
 
const int maxNum=205
const int maxInt=99999999
 
typedef struct Edge 

    int u,v;//起点,终点 
    int weight;//权重 
}Edge; 
 
Edge edge[maxNum];//保存边的值 
int dist[maxNum];//结点到源点的最小距离 
 
int nodeNum,edgeNum,start,end;//节点数,边数,起点,终点 
 
//松弛计算 
void relax(int u,int v,int weight) 

    if(dist[v]>dist[u]+weight) 
    { 
        dist[v]=dist[u]+weight; 
    } 

 
bool Bellman_Ford() 

    int i,j; 
    for( i=0;i<nodeNum-1;i++) 
        for( j=0;j<edgeNum;j++) 
        { 
            relax(edge[j].u,edge[j].v,edge[j].weight); 
        } 
    bool flag=1
    //判断是否有负环,这道题目不存在负环,所以这个可以去掉 
    for( i=0;i<edgeNum;i++) 
        if(dist[edge[i].v]>dist[edge[i].u]+edge[i].weight) 
        { 
            cout<<dist[edge[i].v]<<endl<<dist[edge[i].u]<<endl<<edge[i].weight<<endl; 
            flag=0
            break
        } 
    return flag; 

 
int main(void

    int point,n,i; 
    while(scanf("%d%d",&nodeNum,&edgeNum)==2
    { 
        for(i=0;i<nodeNum;i++) 
            dist[i]=maxInt; 
         
        for(i=0;i<edgeNum;i++) 
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].weight); 
 
        scanf("%d%d",&start,&end); 
        dist[start]=0
 
        if(edge[i].u==start) 
            dist[edge[i].v]=edge[i].weight; 
 
        if(Bellman_Ford()) 
        { 
            if(dist[end]==maxInt) 
                printf("-1\n"); 
            else 
                printf("%d\n",dist[end]); 
        }     
        else 
        { 
            printf("-1\n"); 
        } 
    } 
    return 0

 

 

 

AC代码(SPFA算法):

 

#include<iostream> 
using namespace std; 
 
const int maxNum=205
const int maxInt=99999999
 
int map[maxNum][maxNum]; 
int dis[maxNum]; 
char vst[maxNum]; 
 
int nodeNum,edgeNum,start,end; 
 
int SPFA() 

    int i,pri,end,p,Q[maxNum]; 
    memset(vst,0,sizeof(vst)); 
 
    for( i=0;i<maxNum;i++) 
        Q[i]=0
 
    for(i=0;i<nodeNum;i++) 
        dis[i]=maxInt; 
 
    dis[start]=0
    vst[start]=1
    Q[0]=start; 
    pri=0
    end=1
    while(pri<end) 
    { 
        p=Q[pri]; 
        for(i=0;i<nodeNum;i++) 
        { 
            if(dis[p]+map[p][i]<dis[i]) 
            { 
                dis[i]=dis[p]+map[p][i]; 
                if(!vst[i]) 
                { 
                    Q[end++]=i; 
                    vst[i]=1
                } 
            } 
        } 
        vst[p]=0
        pri++; 
    } 
    return 1

 
int main(void

    int i,s,e,w,j; 
    while(scanf("%d%d",&nodeNum,&edgeNum)==2
    { 
        for(i=0;i<nodeNum;i++) 
            for(j=0;j<nodeNum;j++) 
            { 
                map[i][j]=maxInt; 
            } 
 
        for(i=0;i<edgeNum;i++) 
        { 
            scanf("%d%d%d",&s,&e,&w); 
            if(map[s][e]>w) 
                map[s][e]=map[e][s]=w; 
        } 
 
        scanf("%d%d",&start,&end); 
     
        if(SPFA()) 
        { 
            if(dis[end]==maxInt) 
                printf("-1\n"); 
            else 
            { 
                printf("%d\n",dis[end]); 
            } 
        }     
        else 
        { 
            printf("-1\n"); 
        } 
    } 
    return 0

 

 

posted on 2011-08-14 00:15  cchun  阅读(230)  评论(0编辑  收藏  举报