poj 3268 最短路

***题意:在x这个点有个聚会,其他的点要到x这个点,然后再会自己原始的点,求一来一回最大的那个距离

做法:两边dijstra算法,因为是单向图,要注意更新顺序***

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<algorithm>

using namespace std;
#define N 1010
#define INF 0x3f3f3f3f

int maps[N][N];
int n, m, x;
int dist1[N], dist2[N], vis[N];

void Init()
{
    for(int i=1; i<=n; i++)
    for(int j=1; j<=n; j++)
    maps[i][j]=i==j ? 0 : INF;
}

void dij()
{
    for(int i=1; i<=n; i++)
        dist1[i]=maps[i][x];

    memset(vis, 0, sizeof(vis));
    vis[x]=1;
    for(int i=1; i<=n; i++)
    {
        int Min=INF, index=-1;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&dist1[j]<Min)
            {
                Min=dist1[j];
                index=j;
            }
        }
        if(index==-1) break;
        vis[index]=1;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&dist1[j]>maps[j][index]+dist1[index])
                dist1[j]=maps[j][index]+dist1[index];
        }
    }
    for(int i=1; i<=n; i++)
        dist2[i]=maps[x][i];

    memset(vis, 0, sizeof(vis));
    vis[x]=1;
    for(int i=1; i<=n; i++)
    {
        int Min=INF, index=-1;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&dist2[j]<Min)
            {
                Min=dist2[j];
                index=j;
            }
        }
        if(index==-1) break;
        vis[index]=1;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&dist2[j]>dist2[index]+maps[index][j])
                dist2[j]=dist2[index]+maps[index][j];
        }
    }
}

int main()
{
    while(~scanf("%d%d%d", &n, &m, &x))
    {
        Init();
        int u, v, len;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d", &u, &v, &len);
            maps[u][v]=min(len, maps[u][v]);
        }
        dij();

        int ans=-1;

        for(int i=1; i<=n; i++)
        {
            if(dist1[i]+dist2[i]>ans)
                ans=dist1[i]+dist2[i];
        }
        printf("%d
", ans);
    }
    return 0;
}
View Code

 ***两遍spfa,第二次的spfa要使用开始建的反向图,建的反向图也就是以x为如点,dist1里存就是其他店到x的距离***

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<algorithm>

using namespace std;
#define N 101000
#define INF 0x3f3f3f3f

int n, m, x;
int dist[N], head[N], dist1[N], head1[N], vis[N], k, k1;

struct node
{
    int v, len, next;
} a[N], b[N];

void add(int u, int v, int len)
{
    a[k].v=v;
    a[k].len=len;
    a[k].next=head[u];
    head[u]=k++;
}

void add1(int u, int v, int len)
{
    b[k1].v=v;
    b[k1].len=len;
    b[k1].next=head1[u];
    head1[u]=k1++;
}

int spfa()
{
    queue<int> q;
    q.push(x);
    dist[x]=0;
    vis[x]=1;

    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        vis[t]=0;
        for(int i=head[t]; i!=-1; i=a[i].next)
        {
            int v=a[i].v;
            if(dist[v]>dist[t]+a[i].len)
            {
                dist[v]=dist[t]+a[i].len;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(x);
    dist1[x]=0;
    vis[x]=1;

    while(!Q.empty())
    {
        int t=Q.front();
        Q.pop();
        vis[t]=0;
        for(int i=head1[t]; i!=-1; i=b[i].next)
        {
            int v=b[i].v;
            if(dist1[v]>dist1[t]+b[i].len)
            {
                dist1[v]=dist1[t]+b[i].len;
                if(!vis[v])
                {
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
    int ans=-1;
    for(int i=1; i<=n; i++)
    {
        if(ans<dist[i]+dist1[i]&&dist[i]!=INF&&dist1[i]!=INF)
            ans=dist[i]+dist1[i];
    }
    return ans;
}

int main()
{
    int u, v, len;
    while(~scanf("%d%d%d", &n, &m, &x))
    {
        memset(dist, INF, sizeof(dist));
        memset(dist1, INF, sizeof(dist1));
        memset(head, -1, sizeof(head));
        memset(head1, -1, sizeof(head1));
        memset(vis, 0, sizeof(vis));
        k=k1=1;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d", &u, &v, &len);
            add(u, v, len);
            add1(v, u, len);
        }
        int ans=spfa();

        printf("%d
", ans);
    }
    return 0;
}
 
View Code
原文地址:https://www.cnblogs.com/9968jie/p/5688293.html