Poj(2679),SPFA,邻接表(主流写法)

题目链接:http://poj.org/problem?id=3268

题意:

有编号为1-N的牛,它们之间存在一些单向的路径。给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求这些牛中所花的最长的来回时间是多少。

思路:

很骚的写法,这里用了两个数组标记,head,next,他每次找到下一个结点后,head就赋给next了,然后head又是一条新的边,这样,我在遍历这个链表的时候,就能从后往前遍历了,我推了一个小时。

然后这里的if语句也很重要,要先松弛,再看前一个结点有没有被访问,没有被访问就加到队列里去,并标记。这里我Debug7小时才发现这个错误。内心是崩溃的。

#include <stdio.h>
#include <string.h>
#include <queue>

using namespace std;

#define N 1005
#define M 2000010
#define INF 0x3f3f3f3f

int head[M],next[500050];
int dis[N];
int cnt[N];
bool vis[N];
int n,m,send,x1,y1;
int e;

struct Node
{
    int u;
    int v;
    int c;
    Node() {}
    Node(int u,int v,int c) : u(u),v(v),c(c) {}
} nodes[M];

void addNode(int u,int v,int c)
{
    nodes[e] = Node(u,v,c);
    next[e] = head[u];
    head[u] = e++;
}

void init()
{
    memset(head,-1,sizeof(head));
    memset(next,-1,sizeof(next));

    memset(cnt,0,sizeof(cnt));

    e = 1;
    for(int i=0; i<m; i++)
    {
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        addNode(u,v,c);
        //addNode(v,u,c);
    }
}

bool relax(int u,int v,int c)
{
    if(dis[v]>dis[u]+c)
    {
        dis[v] = dis[u] + c;
        return true;
    }
    return false;
}

int spfa(int src,int send)
{
    memset(vis,false,sizeof(vis));
    for(int i=1; i<=n; i++)
        dis[i] = INF;

    dis[src] = 0;
    vis[src] = true;

    queue<int> Q;
    Q.push(src);
    while(Q.size())
    {
        int f = Q.front();
        Q.pop();
        vis[f] = false;
        for(int i=head[f]; i+1; i=next[i])
        {
            if(relax(f,nodes[i].v,nodes[i].c)&&!vis[nodes[i].v])
            {
                //if((++cnt[Nodes[i].v]>n)) return -1;
                Q.push(nodes[i].v);
                vis[nodes[i].v] = true;
            }
        }
    }

    return dis[send];
}

int main()
{

    scanf("%d%d%d",&n,&m,&send);

    init();
    int tmp = -0x3f3f3f3f;
    for(int i=1; i<=n; i++)
    {

        if(i==send) continue;
        x1 = spfa(i,send);
        y1 = spfa(send,i);
        if(tmp<(x1+y1))
            tmp = x1+y1;
    }
    printf("%d
",tmp);


    return 0;
}
原文地址:https://www.cnblogs.com/TreeDream/p/5734670.html