poj 2679 Adventurous Driving(SPFA 负环)

/*
- -
这题做了一天.....粗心害死人啊 题目描述恶心 数据更恶心... 
先处理一下能走的边 能走的点(到这建边从终点跑一下.)
然后就是SPFA了 注意负环的判断 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1110
#define maxm 10010
#define inf 999999999
using namespace std;
int n,m,num,num2,head[maxn],s,t,vis[maxm];
int ans[maxm],size,f[maxn],falg,Dis[maxn],Ti[maxn];//ans存能走的边 并不是一个点对应一条边 要用maxm! 
int sum[maxn],can[maxn],head2[maxn];
struct node
{
    int u,v,ti,si,pre;
}e[maxm],e2[maxm];
queue<int>q;
int init()
{
    int x=0;char s;bool f=0;s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    if(f)return -x;else return x;
}
void Add(int from,int to,int cost,int len)
{
    num++;
    e[num].u=from;
    e[num].v=to;
    e[num].si=len;
    e[num].ti=cost;
    e[num].pre=head[from];
    head[from]=num;
}
void Add2(int from,int to,int cost,int len)
{
    num2++;
    e2[num2].u=from;
    e2[num2].v=to;
    e2[num2].si=len;
    e2[num2].ti=cost;
    e2[num2].pre=head2[from];
    head2[from]=num2;
}
void Edge_can()//能走的边 
{
    for(int i=0;i<=n;i++)
      {
        int minn=inf,k;
        for(int j=head[i];j;j=e[j].pre)
          if(e[j].ti<minn)
            minn=e[j].ti;
        for(int j=head[i];j;j=e[j].pre)
          if(e[j].ti==minn)
            ans[++size]=j;
      }
    for(int i=1;i<=size;i++)vis[ans[i]]=1;
}
void Bfs(int x)
{
    queue<int>qi;
    qi.push(x);
    can[x]=1;
    while(!qi.empty())
      {
          int k=qi.front();
          qi.pop();
          for(int i=head2[k];i;i=e2[i].pre)
            if(can[e2[i].v]==0)
              {
                qi.push(e2[i].v);
                can[e2[i].v]=1;
            }
      }
}
void Point_can()//到这建边搜能走的点 
{
    for(int i=1;i<=num;i++)
      if(vis[i])
        Add2(e[i].v,e[i].u,e[i].ti,e[i].si);
    Bfs(t);
}
void SPFA(int st)
{
    q.push(st);
    f[st]=1;
    sum[st]++;
    Dis[st]=0;
    Ti[st]=0;
    while(!q.empty())
      {
          int now=q.front();
          q.pop();
          f[now]=0;
          if(sum[now]>n+5)//负环死循环 
            {
                falg=1;
                break;
          }
          for(int i=head[now];i;i=e[i].pre)
            if((Ti[now]+e[i].ti<Ti[e[i].v]||(Ti[now]+e[i].ti==Ti[e[i].v]&&
            Dis[now]+e[i].si<Dis[e[i].v]))&&vis[i]&&can[e[i].v])//没有 f[e[i].v]==0 !!!
              {
                Ti[e[i].v]=Ti[now]+e[i].ti;
                Dis[e[i].v]=Dis[now]+e[i].si;
                if(f[e[i].v]==0)
                  {
                    q.push(e[i].v);
                  f[e[i].v]=1;
                  sum[e[i].v]=sum[now]+1;    
                }
            }
      }
}
int main()
{
    while(~scanf("%d%d%d%d",&n,&m,&s,&t))
      {
          n--;
          memset(head,0,sizeof(head));memset(ans,0,sizeof(ans));//多组数据....注意初始化 
          memset(vis,0,sizeof(vis));memset(can,0,sizeof(can));
          memset(f,0,sizeof(f));memset(sum,0,sizeof(sum));
          memset(Dis,127/3,sizeof(Dis));memset(Ti,127/3,sizeof(Ti));
          memset(head2,0,sizeof(head2));
          size=0;num=0;falg=0;num2=0;
          int ui,vi,dis,cost1,cost2;
          for(int i=1;i<=m;i++)
            {
                ui=init();
                vi=init();
                cost1=init();
                dis=init();
                cost2=init();
                Add(ui,vi,cost1,dis);
                Add(vi,ui,cost2,dis);
          }
        Edge_can();
        Point_can();
        if(can[s]==0)//跑不到终点  
          {
              printf("VOID\n");
              continue;
          }
        SPFA(s);
        if(falg==1)printf("UNBOUND\n");//能跑到 并且有负环  
        if(falg==0)printf("%d %d\n",Ti[t],Dis[t]);
      }
    return 0;
}

 

posted @ 2016-05-12 15:11  一入OI深似海  阅读(302)  评论(0编辑  收藏  举报