Poj2679 spfa算法深度应用

题目大意:给你村庄和村庄之间的距离和费用,如果这个村庄的费用可以无限小就输出UNBOUND,如果这两个村庄之间没有路就输出VOID,否则则输出在满足最小费用下的最短路。

算法思路:判断村庄费用无限小其实就是判断在所给的两个村庄a,b之间是否存在负环,注意全图存在负环但这两个村庄之间不存在负环的情况要考虑啊!因此我们要判断一下如果存在任意一个入队次数>n的点与b连通,或者本身b的入队次数就>n就说明a与b之间存在负环,输出UNBOUND,如果dist[b]==INF就说明a到不了b就输出VOID,否则输出最小费用和最小距离即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
int n,m,a,b,e,num1,num2,num3,num4,num5;
int head[2005],next[10050],dist[2005],dist2[2005];
bool visited[2005];
char str[50];
int num[2005];
bool flag;
typedef struct Edge
{
    int u;
    int v;
    int c;
    int value;
};
Edge edges[10050];
void addNode(int u,int v,int c,int value)
{
    //注意见图的时候这里要进行判断,某个点的单链表中如果有多条边的话,我们只取费用最小的那一个点组成单链表
    if(head[u]!=-1&&value>edges[head[u]].value)
        return;
    if(head[u]!=-1&&value<edges[head[u]].value)
        head[u]=-1;
    edges[e].u=u;
    edges[e].v=v;
    edges[e].c=c;
    edges[e].value=value;
    next[e]=head[u];
    head[u]=e++;
}
bool relax(int u,int v,int c,int value)
{

    if(dist2[v]>dist2[u]+value||dist2[v]==dist2[u]+value&&dist[v]>dist[u]+c)
    {
        dist2[v]=dist2[u]+value;
        dist[v]=dist[u]+c;
        return true;
    }

    return false;
}

bool spfa(int src)
{
    memset(visited,false,sizeof(visited));
    memset(num,0,sizeof(num));
    for(int i=0;i<n;i++)
    {
        dist[i]=INF;
        dist2[i]=INF;
    }
    dist[src]=0;
    dist2[src]=0;
    queue<int>que;
    visited[src]=true;
    que.push(src);

    while(!que.empty())
    {
        int q=que.front();
        que.pop();
        visited[q]=false;
        for(int i=head[q];i+1;i=next[i])
        {
            if(relax(q,edges[i].v,edges[i].c,edges[i].value)&&!visited[edges[i].v])
            {
                if(++num[edges[i].v]>n)
                    return false;
                visited[edges[i].v]=true;
                que.push(edges[i].v);
            }
        }

    }
    return true;
}
void dfs(int x,int y)
{
    visited[x]=true;
    if(x==y)//如果存在num[x]>n的点与结束点相连接的话,就标记
    {
        flag=true;
        return;
    }
    for(int i=head[x];i+1;i=next[i])
    {
            if(!visited[edges[i].v])
            {
                dfs(edges[i].v,y);
            }
    }
}
int main()
{
    while(~scanf("%d%d%d%d",&n,&m,&a,&b))
    {
        e=0;flag=false;
        memset(head,-1,sizeof(head));
        memset(next,-1,sizeof(next));
        memset(edges,0,sizeof(edges));
        for(int i=0; i<m; i++)
        {
            int sum=0;
            int nn=0;
            bool isfu=false;
            scanf("%s",str);
            sscanf(str,"(%d,%d,%d[%d]%d)",&num1,&num2,&num3,&num4,&num5);
            addNode(num1,num2,num4,num3);
            addNode(num2,num1,num4,num5);

        }


         bool ok=spfa(a);

        for(int i=0;i<n;i++)
        {
            if(num[i]>n)
            {
                  memset(visited,false,sizeof(visited));
                flag=false;
                dfs(i,b);
                if(flag)
                    break;

            }
        }

        if(dist[b]==INF)
        {
            printf("VOID\n");
        }
        else
        {
            if(ok)
                printf("%d %d\n",dist2[b],dist[b]);
            else
            {
                if(flag||num[b]>n)
                     printf("UNBOUND\n");
                else
                    printf("%d %d\n",dist2[b],dist[b]);
            }
        }


    }
}

猜你喜欢

转载自huyifan951124.iteye.com/blog/2315491