最短路径

floyd

判断连通性

for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                mp[i][j]=mp[i][j]||(mp[i][k]&&mp[k][j]);
                //if(mp[i][j]||(mp[i][k]&&mp[k][j]))
                    mp[i][j]=true;

求最短路径

for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            if(mp[i][j]>mp[i][k]+mp[k][j])
                mp[i][j]=mp[i][k]+mp[k][j]);

dijkstra

/*
5 7
1 2 3
1 5 7
1 4 2
2 3 1
2 5 8
3 4 7
4 5 4
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e2+5;
const int inf=0x7f7f7f7f;
int maxn,n;//maxn为结点个数,n为边的条数
int mp[N][N],dis[N];//dis即为最短路径
void dijkstra(int v0)
{
    //初始化,以v0为起点
    bool s[maxn];//用于存储已经走过的结点
    for(int i=1;i<=maxn;i++){
        s[i]=false;
        dis[i]=mp[v0][i];
    }
    s[v0]=true;
    dis[v0]=0;
    //
    for(int i=2;i<=maxn;i++){//已经走过一个结点,所以从2开始
        int mindis=inf,u;//u为下一步走的结点
        for(int j=1;j<=maxn;j++){
            if(!s[j]&&dis[j]<mindis){
                u=j;mindis=dis[j];
            }
        }
        s[u]=true;//该结点已经走过
        //更新最短路径及距离
        for(int j=1;j<=maxn;j++)
            if(!s[j]&&mp[u][j]<inf) dis[j]=min(dis[j],dis[u]+mp[u][j]);
            //mp[u][j]<inf可以防止溢出
    }
}
int main()
{
    memset(mp,0x7f,sizeof(mp));
    scanf("%d%d",&maxn,&n);
    for(int i=0;i<n;i++)
    {
        int x,y,value;
        scanf("%d%d%d",&x,&y,&value);
        mp[x][y]=value;
        mp[y][x]=value;//无向网图
    }
    int v;//原点
    scanf("%d",&v);
    dijkstra(v);
    for(int i=1;i<=maxn;i++)
        printf("%d  ",dis[i]);
    return 0;
}

用vector存图的dijkstra

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int inf=0x3f3f3f3f;
struct node{
    int ed,len;
    node(){}
    node(int ed,int len):ed(ed),len(len){}
};
vector<node>E[105];
int main()
{
    ios::sync_with_stdio(false);
    int n,m;
    while(cin>>n>>m){
        if(n==0&&m==0)
            break;
        for(int i=0;i<105;i++)
            E[i].clear();
        for(int i=1;i<=m;i++){
            int a,b,c;
            cin>>a>>b>>c;
            E[a].push_back(node(b,c));
            E[b].push_back(node(a,c));
        }
        bool s[105];
        int dis[105];
        memset(s,0,sizeof s);
        memset(dis,0x3f,sizeof dis);
        for(int i=0;i<E[1].size();i++)
            dis[E[1][i].ed]=E[1][i].len;
        dis[1]=0;
        s[1]=true;
        for(int i=2;i<=n;i++){
            int u,mindis=inf;
            for(int j=1;j<=n;j++){
                if(!s[j]&&dis[j]<mindis){
                    u=j;
                    mindis=dis[j];
                }
            }
            s[u]=true;
            for(int j=0;j<E[u].size();j++)
            if(!s[E[u][j].ed])
                dis[E[u][j].ed]=min(dis[E[u][j].ed],dis[u]+E[u][j].len);
        }
        cout<<dis[n]<<endl;
    }
    return 0;
}
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
struct node{
    int ed,len,next;
}e[20050];
int p[105],num;
void add(int st,int ed,int len)
{
    e[num].ed=ed;
    e[num].len=len;
    e[num].next=p[st];
    p[st]=num;
    num++;
}
int main()
{
    ios::sync_with_stdio(false);
    int n,m;
    while(cin>>n>>m){
        if(n==0&&m==0)
            break;
        memset(e,-1,sizeof e);
        memset(p,-1,sizeof p);
        num=0;
        for(int i=1;i<=m;i++){
            int a,b,c;
            cin>>a>>b>>c;
            add(a,b,c);
            add(b,a,c);
        }
        bool s[105];
        int dis[105];
        memset(dis,0x3f,sizeof dis);
        memset(s,0,sizeof s);
        dis[1]=0;
        for(int i=1;i<=n;i++){
            int mindis=inf,u;
            for(int j=1;j<=n;j++){
                if(!s[j]&&dis[j]<mindis){
                    u=j;
                    mindis=dis[j];
                }
            }
            s[u]=true;
            for(int j=p[u];j!=-1;j=e[j].next){
                if(!s[e[j].ed])
                dis[e[j].ed]=min(dis[e[j].ed],dis[u]+e[j].len);
            }
        }
        cout<<dis[n]<<endl;
    }
    return 0;
}

vector存图可以减少内存开销
Struct node{
int en,len;
};
Vector E[num]; //num为点的个数。
其中E[u][j]表示结点u到结点j的路径

邻接表也可以减少内存开销
Struct node
{
int en,len,next;
}E[MAXM];
Int p[MAXN],num;
用结构体数组存下所有的边权,下一节点。
借助p数组标记,节点id,在E数组中的首位置。

初始化

Void init()
{
Memset(p,-1,sizeof(p));
Num=0;//num是存入E的第几条边
}

加边

Void add(int st,int en,int len)
{
E[num].en=en;
E[num].len=len;
E[num].next=p[st];//头插法
P[st]=num;
num++;
}
每次加边,可得以st为首节点,它邻接点存的位置p[st]。

遍历结点

For(i=p[u];i!=-1;i=E[i].next)
{
int v=E[i].en;
int length=E[i].len;
//i的初值为u点的第一个临界点在E[]数组的下标。然后i=E[i].next,递推找到下一个u的邻接点。知道为-1(p的初值)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值