Adventurous Driving - POJ 2679 最短路+负环

76 篇文章 0 订阅

Adventurous Driving
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1511 Accepted: 426

Description

After a period of intensive development of the transportation infrastructure, the government of Ruritania decides to take firm steps to strengthen citizens' confidence in the national road network and sets up a compensation scheme for adventurous driving (CSAD). Those driving on a road with holes, bumps and other entertaining obstacles get compensation; those driving on a decent road pay tax. These compensations and taxes are obtained and paid in cash on entry on each road and depend on the entry point on the road. What you get and pay driving on a road from A to B may be different from what you get and pay driving on the same road from B to A. The Ruritarian authorities call fee the amount of money paid as tax or obtained as compensation on entry on a road. A positive fee is a tax; a negative fee stands for compensation. 
John Doe plans to take advantage of CSAD for saving money he needs to repair his old car. When driving from A to B, John follows a path he calls optimal: a path that is rewarding and has the minimal length out of the paths with the minimal weight from A to B. In John's opinion, a path is rewarding if all the roads in the path are rewarding, and a road (X,Y) is rewarding if it has the minimal entry fee out of the roads leaving X. The weight of a path is the sum of the entry fees paid along the path. The length of a path cumulates the length of the roads in the path. The problem is helping John to compute the weight and the length of an optimal path from A to B on a given map. 
For example, on the illustrated road map vertices designate cities and edges stand for roads. The label fuv[L]fvu of the road (u,v) shows the fee fuv for driving from u to v, the fee fvu for driving from v to u, and the length L of the road. The path (0,2,4,3,5) from 0 to 5 is optimal: it is rewarding, has weight 2 (-1+3+0+0) and length 50 (5+10+5+30). The path (0,1,4,3,5), although rewarding and of weight 2, has length 51. The path (0,3,5) has weight 0 and length 20 but it is not rewarding.

Input

Write a program that reads several data sets from a text file. Each data set encodes a road map and starts with four integers: the number 1<=n<=1100 of towns on the map, the number 0<=m<=5000 of roads, the departure town 0<=A<=n-1, and the destination town 0<=B<=n-1. Follow m data quintuples (u,v,fuv[L]fvu), where u and v are town identifiers (integers in the range 0..n-1), 100<=fuv, fvu<=100 are integer fees for driving on the road (u,v), and 1<=L<=100 is the integer length of the road. The quintuples may occur in any order. Except the quintuples, which do not contain white spaces, white spaces may occur freely in input. Input data terminate with an end of file and are correct.

Output

For each data set, the program prints – from the beginning of a line – the weight and the length of an optimal path, according to John's oppinion, from A to B. If there is no optimal path from A to B the text VOID is printed. If the weight of the optimal path from A to B has no lower bound the text UNBOUND is printed.

Sample Input

3 3 0 2 (0,1,0[1]0) (0,2,1[1]0) (1,2,1[1]0)
3 3 0 2 (0,1,-1[1]1) (0,2,0[1]0) (1,2,0[1]1)
7 11 0 5 (0,1,-1[6]4) (0,2,-1[5]4) (0,3,0[1]0)  (1,4,3[10]1)
(2,4,3[10]1) (3,4,0[5]0)  (3,5,0[30]0) (3,5,1[20]0)
 (4,6,0[3]1)  (6,5,1[8]0)  (6,6,0[2]-1)

Sample Output

VOID
UNBOUND
2 50

题意:每次给定u,v,fuv[len],fvu,len表示uv之间的,fuv表示从u到v的费用,fvu表示从v到u的费用。每次点只能走它下一个费用最低的路线。求从A到B在花费最小的情况下,路径长度的最小值,并输出这两个值。如果不存在路径输出VOID,如果有负环输出UNBOUND。

思路:首先保证每次点只走下一个费用最低的路线。然后用spfa,求是否存在负环。如果有负环,判断这些负环内的点是否能通向B,如果可以的话,就是UNBOUND,否则输出结果。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node
{
    int v,len,cost,next;
}edge[10010];
int n,m,A,B,Head[1110],tot,INF=1e9,c[1110],length[1110],times[1110];
queue<int> qu;
bool vis[1110];
char ch;
void add(int u,int v,int len,int cost)
{
    if(Head[u]!=-1 && edge[Head[u]].cost<cost)
      return;
    if(Head[u]!=-1 && edge[Head[u]].cost>cost)
      Head[u]=-1;
    edge[tot].v=v;
    edge[tot].len=len;
    edge[tot].cost=cost;
    edge[tot].next=Head[u];
    Head[u]=tot++;
}
void spfa(int u)
{
    int i,j,k,v;
    for(i=0;i<n;i++)
       c[i]=length[i]=INF;
    memset(times,0,sizeof(times));
    memset(vis,0,sizeof(vis));
    while(!qu.empty())
      qu.pop();
    c[u]=length[u]=0;
    qu.push(u);vis[u]=1;
    while(!qu.empty())
    {
        u=qu.front();


        qu.pop();
        vis[u]=0;
        if(++times[u]>n+5)
          return;
        for(i=Head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(c[v]>c[u]+edge[i].cost || (c[v]==c[u]+edge[i].cost && length[v]>length[u]+edge[i].len))
            {
                c[v]=c[u]+edge[i].cost;
                length[v]=length[u]+edge[i].len;
                if(!vis[v])
                {
                    vis[v]=1;
                    qu.push(v);
                }
            }
        }
    }
}
void dfs(int u)
{
    int i,j,k,v;
    vis[u]=1;
    for(i=Head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(!vis[v])
          dfs(v);
    }
}
int main()
{
    int i,j,k,u,v,fuv,fvu,len;
    while(~scanf("%d%d%d%d",&n,&m,&A,&B))
    {
        memset(Head,-1,sizeof(Head));
        tot=0;
        for(i=1;i<=m;i++)
        {
            while(scanf("%c", &ch), ch != '(');
              scanf("%d,%d,%d[%d]%d)", &u, &v, &fuv, &len, &fvu);
            add(u,v,len,fuv);
            add(v,u,len,fvu);
        }
        spfa(A);
        memset(vis,0,sizeof(vis));
        for(i=0;i<n;i++)
           if(times[i]>n)
             dfs(i);
        if(c[B]==INF)
          printf("VOID\n");
        else if(vis[B])
          printf("UNBOUND\n");
        else
          printf("%d %d\n",c[B],length[B]);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值