ACM: spfa+dfs 图论题 poj 2679

来源:互联网 发布:麻瓜编程 爬虫 编辑:程序博客网 时间:2024/06/06 02:34
                                                                  Adventurous Driving
Description
After a period ofintensive development of the transportation infrastructure, thegovernment of Ruritania decides to take firm steps to strengthencitizens' confidence in the national road network and sets up acompensation scheme for adventurous driving (CSAD). Those drivingon a road with holes, bumps and other entertaining obstacles getcompensation; those driving on a decent road pay tax. Thesecompensations and taxes are obtained and paid in cash on entry oneach road and depend on the entry point on the road. What you getand pay driving on a road from A to B may be different from whatyou get and pay driving on the same road from B to A. TheRuritarian authorities call fee the amount of money paid as tax orobtained as compensation on entry on a road. A positive fee is atax; a negative fee stands for compensation.
John Doe plans to take advantage of CSAD for saving money he needsto repair his old car. When driving from A to B, John follows apath he calls optimal: a path that is rewarding and has the minimallength out of the paths with the minimal weight from A to B. InJohn's opinion, a path is rewarding if all the roads in the pathare rewarding, and a road (X,Y) is rewarding if it has the minimalentry fee out of the roads leaving X. The weight of a path is thesum of the entry fees paid along the path. The length of a pathcumulates the length of the roads in the path. The problem ishelping John to compute the weight and the length of an optimalpath from A to B on a given map.
For example, on the illustrated road map vertices designate citiesand 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 drivingfrom 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 rewardingand of weight 2, has length 51. The path (0,3,5) has weight 0 andlength 20 but it is not rewarding.

Input

Write a program thatreads several data sets from a text file. Each data set encodes aroad map and starts with four integers: the number1<=n<=1100 of towns on the map, thenumber 0<=m<=5000 of roads, thedeparture town 0<=A<=n-1, and thedestination town 0<=B<=n-1. Follow mdata 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 integerlength of the road. The quintuples may occur in any order. Exceptthe quintuples, which do not contain white spaces, white spaces mayoccur freely in input. Input data terminate with an end of file andare correct.

Output

For each data set,the program prints – from the beginning of a line – the weight andthe length of an optimal path, according to John's oppinion, from Ato B. If there is no optimal path from A to B the text VOID isprinted. If the weight of the optimal path from A to B has no lowerbound 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

Hint

An input/outputsample is in the table above. The first data set encodes a road mapwith no optimal path from 0 to 2. The second data set correspondsto a map whose optimal path from 0 to 2 has an unbound weight. Thethird data set encodes the road map shown in the abovefigure.

题意:  一个图, 知道每条边的信息, 并且图示一个有向图. fuv != fvu
         每条路上有长度和费用, 现在要求出从A到B最小的费用并且长度尽可能的短.
         并且判断A到B中是否最短路有下限(是否有负环) 和 能不能联通.

解题思路:
             1. 最短路和最小费用可以用spfa来求解.
             2. 难点是 怎么判断A到B中的路径有没有环,而不是判断整个图中有没有环.
            问题分析:
                         (1). 利用spfa算法中判断环的标记.times. 如果一个点再环上一定有times[p] >n,
                       显然, 我们只需要枚举每个点(0~n-1), 如果times[p] > n 并且 p可以到达B,表示
                    A到B有负环.

代码:
 
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define MAX 20005
const int INF = (1<<30);

struct node
{
    int v;
    int w,len;
    intnext;
}edges[MAX];

int n, m;
int first[MAX];
int num;

int dist[MAX];
int length[MAX];
bool vis[MAX], state[MAX];
int times[MAX];

int start, end;
int flag;

void add(int u,int v,int len,int w)
{
    if(first[u]!= -1 && w >edges[first[u]].w) return ;
    if(first[u]!= -1 && w <edges[first[u]].w) first[u] = -1;
    edges[num].v= v;
    edges[num].w= w;
   edges[num].len = len;
   edges[num].next = first[u];
    first[u] =num++;
}

void read_graph()
{
   memset(first,-1,sizeof(first));
   memset(edges,0,sizeof(edges));
    num =0;
    charch;
    int u, v,len, w, anti_w;
    for(int i =0; i < m; ++i)
    {
      while(scanf("%c",&ch) , ch != '(' );
      scanf("%d,%d,%d[%d]%d)",&u,&v,&w,&len,&anti_w);
      add(u,v,len,w);
      add(v,u,len,anti_w);
    }
}

bool spfa()
{
   memset(vis,false,sizeof(vis));
//   memset(length,INF,sizeof(length));
    for(int i =0; i < n; ++i)
    {
       length[i] =(i == start ? 0 : INF);
    }
//   memset(dist,INF,sizeof(dist));
    for(int i =0; i < n; ++i)
    {
       dist[i] = (i== start ? 0 : INF);
    }
   memset(times,0,sizeof(times));
    vis[start] =true;
    times[start]= 1;
   queue<int> qu;
   qu.push(start);
   
    while(!qu.empty() )
    {
       int u =qu.front();
      qu.pop();
       vis[u] =false;
       if(times[u]> n) return true;  //判断是否存在负环
       for(int e =first[u]; e != -1; e = edges[e].next)
       {
          if((dist[edges[e].v] > dist[u] + edges[e].w) ||(dist[edges[e].v] == dist[u] + edges[e].w&& length[edges[e].v]> length[u] + edges[e].len)) //同时对长度和费用进行松弛操作
          {
            dist[edges[e].v] = dist[u] + edges[e].w;
            length[edges[e].v] = length[u] + edges[e].len;
             if(!vis[edges[e].v] )
             {
               vis[edges[e].v] = true;
               qu.push(edges[e].v);
               times[edges[e].v]++; //记录点访问次数
             }
          }
       }
    }
    returnfalse;
}

void dfs(int u)
{
    state[u] =true;
    if(u ==end)
    {
       flag =true;
       return;
    }
    for(int e =first[u]; e != -1; e = edges[e].next)
    {
      if(!state[edges[e].v])
         dfs(edges[e].v);
    }
}

void solve()
{
    bool ans =spfa();
    if(dist[end]== INF) printf("VOID\n");
    else
    {
       if(!ans)printf("%d %d\n",dist[end],length[end]);
       else
       {
          for(int i =0; i < n; ++i)
          {
             if(times[i]> n)
             {
               memset(state,false,sizeof(state));
                flag =false;
               dfs(i);
                if(flag)break;
             }
          }
          if(flag ||times[end] > n)
            printf("UNBOUND\n");
          else
             printf("%d%d\n",dist[end],length[end]);
       }
    }
}

int main()
{
//   freopen("input.txt","r",stdin);
   while(scanf("%d %d %d%d",&n,&m,&start,&end)!= EOF)
    {
      read_graph();
      solve();
    }
    return0;
}
0 0
原创粉丝点击