2017.9.9 图论 — 最短路(修邻接表bug---10.20)

Dijkstra:

//不能解决有负边权的图
//从起点一层层向下更新
//与spfa(靠队列实现)相似,源点是一定的,but 实现方式不同 

#include<cstdio>
#define Max 0x3fffffff
int map[1005][1005];
int dis[1005];

void dijkstra(int n)
{
    int visit[1001]={0};
    int min,i,j,k;
    visit[1]=1;
    for(i=1;i<n;++i)
    {
        min=Max;
        k=1;
        for(j=1;j<=n;++j)
        {
            if(!visit[j]&&min>dis[j])
            {
                min=dis[j];
                k=j;
            }
        }
        visit[k]=1;
        for(j=1;j<=n;++j)
        {
            if(!visit[j]&&dis[j]>dis[k]+map[k][j])
                dis[j]=dis[k]+map[k][j];
        }
    }
    printf("%d\n",dis[n]);
}

int main()
{
    int t,n,i,j,from,to,cost;
    while(scanf("%d%d",&t,&n)!=EOF)
    {
        for(i=1;i<=n;++i)
        {
            map[i][i]=0;
            for(j=1;j<i;++j)
                map[i][j]=map[j][i]=Max;
        }
        for(i=1;i<=t;++i)
        {
            scanf("%d%d%d",&from,&to,&cost);
            if(cost<map[from][to])               
                map[from][to]=map[to][from]=cost;
        }
        for(i=1;i<=n;++i)
            dis[i]=map[1][i];
        dijkstra(n);
    }
    return 0;
}

SPFA:

//期望的时间复杂度为o(ke),k为所有顶点的进队次数,k一般<=2 
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 1000001
#define inf 0x7ffffff
using namespace std;

int n,m,tot;
int head[maxn],next[maxn],dist[maxn];
bool vis[maxn];

struct node
{
    int from,to,w;
}e[maxn];

void add(int from,int to,int w)
{
    e[++tot] = (node){from,to,w};
    next[tot] = head[from];
    head[from] = tot;
/*    e[t].from=i;
    e[t].to=j;
    e[t].w=w;
    e[t].next=head[i];
    head[i]=++t;
*/
}
//先将源点入队,再依次取与当前点(已经处理完最短路的点)相邻的点 
void spfa(int s)
{
    queue<int> q;
    for(int i=1;i<=n;i++) dist[i]=inf;   
    q.push(s);
    vis[s]=true;
    dist[s]=0;
    while(!q.empty())
    {//通过for循环解决的是与u相邻的所有点与边,即:处理(取出)一个点,就用for循环更新完与他相邻的点的zdl 
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];i!=-1;i=next[i])
        {//从以源点为起点的边开始循环,e[i].next:当前边的下一条边(同一个起点)
            int v=e[i].to;
            if(dist[v]>dist[u]+e[i].w)
            {
                dist[v]=dist[u]+e[i].w;
                if(!vis[v])//没有在队列中(是否之前入队过,又出队,vis才==0??????) 
                {
                    q.push(v);
                    vis[v]=true;                             
                }
            }
        }
    }
}

int main()
{
    freopen("spfa.in","r",stdin); 
    freopen("spfa.out","w",stdout); 

    int a,b,c,s,e; 
    //t=0; 
    memset(head,-1,sizeof(head)); 
    scanf("%d%d",&n,&m); 
    for(int i=1;i<=m;i++) 
    {
        scanf("%d%d%d",&a,&b,&c); 
        add(a,b,c); 
        //如果双向边边权不一样 也不影响,因为是一直朝着终点走,一条边不会走两遍  
        // !!!
    } 
    //求s->e的最短路(zdl)
    scanf("%d%d",&s,&e); 
    spfa(s); 
    if(dist[e]==inf) printf("-1\n"); 
    else printf("%d",dist[e]); 

    return 0;
}


..........有bug...............
#include<iostream>
#include<cstdio> 
#include<queue>
#define maxx 1000007
using namespace std;

int n,m,tot=0;
int first[maxx],next[maxx],dis[maxx];

struct bian 
{
    int f,t,d;
}b[10005];

void build(int f,int t,int d)
{ 
    b[++tot]=(bian){f,t,d};
    next[tot]=first[f];
    first[f]=tot;
}
queue<int>q;
bool used[10005];
//每次将与当前点相邻的点入队 
void spfa(int x)
{
    for(int i=1;i<=n;i++)
    dis[i]=1e9; 

    dis[x]=0; 
    q.push(x);
    used[x]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        used[u]=0;
        for(int i=first[u];i!=0;i=next[i])
        { 
            int v=b[i].t; 
            if(dis[v]>dis[u]+b[i].d)
            {
                dis[v]=dis[u]+b[i].d;
                if(used[v]==0)
                {
                    q.push(v);
                    used[v]=1; 
                }
            }
        }
    }
}

int main()
{
    cin>>n>>m;

    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        build(x,y,z);
        build(y,x,z);
    }

    spfa(1);
    cout<<dis[n]<<endl;

    return 0;
}

/*..........邻接表存图有bug,待改正

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 1000001
#define inf 0x7ffffff
using namespace std;

int n,m,t;
int head[maxn],dist[maxn];
bool vis[maxn];

struct node
{
    int from,to,w,next;
}e[maxn];

void add(int i,int j,int w)
{
    e[t].from=i;
    e[t].to=j;
    e[t].w=w;
    e[t].next=head[i];
    head[i]=++t;
}

int spfa(int s)
{
    queue<int> q;
    for(int i=1;i<=n;i++) dist[i]=inf;
    q.push(s);
    vis[s]=true;
    dist[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(dist[v]>dist[u]+e[i].w)
            {
                dist[v]=dist[u]+e[i].w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=true;
                }
            }
        }
    }
}

int main()
{
    int a,b,c,s,e;
    t=0;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    scanf("%d%d",&s,&e);
    spfa(s);
    if(dist[e]==inf) printf("-1\n");
    else printf("%d",dist[e]);

    return 0;
}

*/

Floyd:

// for * 3
//n:节点个数

for(int k=1;k<=n;k++)
{
    for(int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            if(dis[i][k] + dis[k][j] < dis[i][j] )
            {
                //更新最短路径
                dis[i][j] = dis[i][k] + dis[k][j];
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值