/*
*State: POJ3268     Accepted    3324K    16MS    C++    1947B
*题目大意:
*        给定一个有向图(可带环),然后要求所有点到特定点e的距离,然后规定每个
*        点到e之后,还要返回原地,注意图是有向图,去跟回来的路径可能不同。
*解题思路:
*        为了减少运算时间,可以建立正图跟反图,然后两遍spfa即可求解。
*     各种最短路均可求,注意复杂度即可。
*/

spfa+邻接表:

View Code
#include <iostream>
#include <queue>
using namespace std;

const int MAXN = 1005;
const int MAXE = 100005;
const int inf = 0x3f3f3f3f;

typedef struct _node
{
    int v, w;
    int next;
    int op;
    _node(): op(0) {}
}N;

N edge[2 * MAXE];
int head[MAXN], cntEdge, endDis[MAXN];

void init(int n)
{
    cntEdge = 0;
    for(int i = 0; i <= n; i++)
    {
        head[i] = -1;
    }
}

void addEdge(int u, int v, int w)
{
    edge[cntEdge].v = v;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 0;
    edge[cntEdge].next = head[u];
    head[u] = cntEdge++;

    edge[cntEdge].v = u;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 1;
    edge[cntEdge].next = head[v];
    head[v] = cntEdge++;
}


int spfa(int s, int n, int dir)//dir == 1反图
{
    int dis[MAXN], vst[MAXN] = {0};
    for(int i = 0; i <= n; i++)
        dis[i] = inf;

    queue<int> Q;
    Q.push(s);
    vst[s] = 1;
    dis[s] = 0;

    while(!Q.empty())
    {
        int pre = Q.front();
        Q.pop();
        vst[pre] = 0;

        for(int f = head[pre]; f != -1; f = edge[f].next)
        {
            if(dir == 0)
            {
                if(edge[f].op == 1)
                    continue;
            }
            else
            {
                if(edge[f].op == 0)
                    continue;
            }

            int son = edge[f].v, w = edge[f].w;
            if(dis[pre] + w < dis[son])
            {
                dis[son] = dis[pre] + w;
                if(!vst[son])
                {
                    vst[son] = 1;
                    Q.push(son);
                }
            }
        }
    }

    int Max = 0;
    if(!dir)
        for(int i = 1; i <= n; i++)
            endDis[i] = dis[i];
    else
    {
        for(int i = 1; i <= n; i++)
        {
            if(endDis[i] + dis[i] > Max)
                Max = endDis[i] + dis[i];
        }
    }
    return Max;
}

int main(void)
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

    int n, m, e;
    while(scanf("%d %d %d", &n, &m, &e) == 3)
    {
        init(n);
        int u, v, w;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            addEdge(u, v, w);
        }
        //正图
        spfa(e, n, 0);
        //反图
        int sol;
        sol = spfa(e, n, 1);

        printf("%d\n", sol);
    }
    return 0;
}

普通dijkstra+邻接表

View Code
//State: POJ3268    Accepted    3304K    32MS    C++    1971B
#include <iostream>
#include <queue>
using namespace std;

const int MAXN = 1005;
const int MAXE = 100005;
const int inf = 0x3f3f3f3f;

typedef struct _node
{
    int v, w;
    int next;
    int op;
    _node(): op(0) {}
}N;

N edge[2 * MAXE];
int head[MAXN], cntEdge, endDis[MAXN];

void init(int n)
{
    cntEdge = 0;
    for(int i = 0; i <= n; i++)
    {
        head[i] = -1;
    }
}

void addEdge(int u, int v, int w)
{
    edge[cntEdge].v = v;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 0;
    edge[cntEdge].next = head[u];
    head[u] = cntEdge++;

    edge[cntEdge].v = u;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 1;
    edge[cntEdge].next = head[v];
    head[v] = cntEdge++;
}


int dijkstra(int s, int n, int dir)//dir == 1反图
{
    int dis[MAXN], vst[MAXN] = {0};
    for(int i = 0; i <= n; i++)
        dis[i] = inf;
    dis[s] = 0;

    for(int i = 0; i < n - 1; i++)
    {
        int Min = INT_MAX, index;
        for(int j = 1; j <= n; j++)
        {
            if(dis[j] < Min && !vst[j])
            {
                Min = dis[j];
                index = j;
            }
        }
        vst[index] = 1;

        for(int f = head[index]; f != -1; f = edge[f].next)
        {
            if(dir == 0)
            {
                if(edge[f].op == 1)
                    continue;
            }
            else
            {
                if(edge[f].op == 0)
                    continue;
            }
            int son = edge[f].v, w = edge[f].w;
            if(dis[index] + w < dis[son] && !vst[son])
                dis[son] = dis[index] + w;
        }
    }
    

    int Max = 0;
    if(!dir)
        for(int i = 1; i <= n; i++)
            endDis[i] = dis[i];
    else
    {
        for(int i = 1; i <= n; i++)
        {
            if(endDis[i] + dis[i] > Max)
                Max = endDis[i] + dis[i];
        }
    }
    return Max;
}

int main(void)
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

    int n, m, e;
    while(scanf("%d %d %d", &n, &m, &e) == 3)
    {
        init(n);
        int u, v, w;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            addEdge(u, v, w);
        }
        //正图
        dijkstra(e, n, 0);
        //反图
        int sol;
        sol = dijkstra(e, n, 1);

        printf("%d\n", sol);
    }
    return 0;
}

优先队列+dijkstra+邻接表

View Code
//State: POJ3268    Accepted 3340K    32MS    C++    2238B
#include <iostream>
#include <queue>
#include <functional>
#include <vector>
using namespace std;

const int MAXN = 1005;
const int MAXE = 100005;
const int inf = 0x3f3f3f3f;

typedef struct _node
{
    int v, w;
    int next;
    int op;
    _node(): op(0) {}
}N;

typedef struct _priNode
{
    int v, dis;
    //_priNode(): dis(inf) {}
    _priNode(int a, int b): v(a), dis(b) {}
    friend bool operator < (const _priNode &n1, const _priNode &n2)
    {
        return n1.dis > n2.dis;
    }
}PN;

N edge[2 * MAXE];
int head[MAXN], cntEdge, endDis[MAXN];

void init(int n)
{
    cntEdge = 0;
    for(int i = 0; i <= n; i++)
    {
        head[i] = -1;
    }
}

void addEdge(int u, int v, int w)
{
    edge[cntEdge].v = v;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 0;
    edge[cntEdge].next = head[u];
    head[u] = cntEdge++;

    edge[cntEdge].v = u;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 1;
    edge[cntEdge].next = head[v];
    head[v] = cntEdge++;
}


int dijkstra(int s, int n, int dir)//dir == 1反图
{
    int dis[MAXN], vst[MAXN] = {0};
    for(int i = 0; i <= n; i++)
        dis[i] = inf;
    
    dis[s] = 0;
    priority_queue<PN> PQ;
    PN pre(s, 0);
    PQ.push(pre);
    
    while(!PQ.empty())
    {
        PN pre = PQ.top();
        PQ.pop();
        vst[pre.v] = 1;

        for(int f = head[pre.v]; f != -1; f = edge[f].next)
        {
            if(dir == 0)
            {
                if(edge[f].op == 1)
                    continue;
            }
            else
            {
                if(edge[f].op == 0)
                    continue;
            }
            int son = edge[f].v, w = edge[f].w;

            if(dis[pre.v] + w < dis[son] && !vst[son])
            {
                dis[son] = dis[pre.v] + w;
                PN pnSon(son, dis[son]);
                PQ.push(pnSon);
            }
        }
    }

    int Max = 0;
    if(!dir)
        for(int i = 1; i <= n; i++)
            endDis[i] = dis[i];
    else
    {
        for(int i = 1; i <= n; i++)
        {
            if(endDis[i] + dis[i] > Max)
                Max = endDis[i] + dis[i];
        }
    }
    return Max;
}

int main(void)
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

    int n, m, e;
    while(scanf("%d %d %d", &n, &m, &e) == 3)
    {
        init(n);
        int u, v, w;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            addEdge(u, v, w);
        }
        //正图
        dijkstra(e, n, 0);
        //反图
        int sol;
        sol = dijkstra(e, n, 1);

        printf("%d\n", sol);
    }
    return 0;
}

优化+Bellman_ford+邻接表

View Code
#include <iostream>
#include <queue>
using namespace std;

const int MAXN = 1005;
const int MAXE = 100005;
const int inf = 0x3f3f3f3f;

typedef struct _node
{
    int u, v, w;
    int next;
    int op;
    _node(): op(0) {}
}N;

N edge[2 * MAXE];
int head[MAXN], cntEdge, endDis[MAXN];

void init(int n)
{
    cntEdge = 0;
    for(int i = 0; i <= n; i++)
    {
        head[i] = -1;
    }
}

void addEdge(int u, int v, int w)
{
    edge[cntEdge].u = u;
    edge[cntEdge].v = v;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 0;
    edge[cntEdge].next = head[u];
    head[u] = cntEdge++;

    edge[cntEdge].u = v;
    edge[cntEdge].v = u;
    edge[cntEdge].w = w;
    edge[cntEdge].op = 1;
    edge[cntEdge].next = head[v];
    head[v] = cntEdge++;
}

int dijkstra(int s, int n, int dir)//dir == 1反图
{
    int dis[MAXN];
    for(int i = 0; i <= n; i++)
        dis[i] = inf;
    dis[s] = 0;

    for(int i = 0; i < n - 1; i++)
    {
        bool flag = false;
        for(int j = 0; j < cntEdge; j++)
        {
            if(dir == 0)
            {
                if(edge[j].op == 1)
                    continue;
            }
            else
            {
                if(edge[j].op == 0)
                    continue;
            }
            int u = edge[j].u, v = edge[j].v;
            int w = edge[j].w;
            if(dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                flag = true;
            }
        }
        if(!flag)
            break;
    }
    //判断负环就免了,此题没有

    int Max = 0;
    if(!dir)
        for(int i = 1; i <= n; i++)
            endDis[i] = dis[i];
    else
    {
        for(int i = 1; i <= n; i++)
        {
            if(endDis[i] + dis[i] > Max)
                Max = endDis[i] + dis[i];
        }
    }
    return Max;
}

int main(void)
{
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
#endif

    int n, m, e;
    while(scanf("%d %d %d", &n, &m, &e) == 3)
    {
        init(n);
        int u, v, w;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            addEdge(u, v, w);
        }
        //正图
        dijkstra(e, n, 0);
        //反图
        int sol;
        sol = dijkstra(e, n, 1);

        printf("%d\n", sol);
    }
    return 0;
}

 

 

posted on 2012-08-18 09:16  cchun  阅读(694)  评论(0编辑  收藏  举报