POJ 1237 The Postal Worker Rings Once

Description

Graph algorithms form a very important part of computer science and have a lineage that goes back at least to Euler and the famous Seven Bridges of Konigsberg problem. Many optimization problems involve determining efficient methods for reasoning about graphs.
计算机科学中的一个非常重要的组成部分就是图论算法,它们都可以追溯到欧拉和著名的哥尼斯堡七桥问题。许多优化问题都需要确定有关图推理的高效方法。
This problem involves determining a route for a postal worker so that all mail is delivered while the postal worker walks a minimal distance, so as to rest weary legs.
该问题就是要为邮递员确定一条路线,让他在投递所有信件的同时只走最短的距离,以节省脚力。
Given a sequence of streets (connecting given intersections) you are to write a program that determines the minimal cost tour that traverses every street at least once. The tour must begin and end at the same intersection.
给定一系列的街道(由路口相互联通),你要写一个程序来确定跑遍所有这些街道所需的最小旅程。旅程结束时必须回到起点的路口。
The ``real-life'' analogy concerns a postal worker who parks a truck at an intersection and then walks all streets on the postal delivery route (delivering mail) and returns to the truck to continue with the next route.
在现实生活中的情况是一个邮递员将它的卡车停在路口,然后跑遍所有的 小巷 来完成投递任务(发邮件),最后回到卡车继续下一次投递任务。
The cost of traversing a street is a function of the length of the street (there is a cost associated with delivering mail to houses and with walking even if no delivery occurs).
穿过一条街所花费的开销是这条街长度的函数(将邮件投递入户会产生开销,行走而没有投递也会产生开销)。
In this problem the number of streets that meet at a given intersection is called the degree of the intersection. There will be at most two intersections with odd degree. All other intersections will have even degree, i.e., an even number of streets meeting at that intersection.
在这个问题中,与一个路口相连的所有街道的数量称为这个路口的“度”。最多存在两个奇数度的路口,其它所有路口的度均为偶数,即有偶数条街道与该路口相连。

Input

The input consists of a sequence of one or more postal routes. A route is composed of a sequence of street names (strings), one per line, and is terminated by the string ``deadend'' which is NOT part of the route. The first and last letters of each street name specify the two intersections for that street, the length of the street name indicates the cost of traversing the street. All street names will consist of lowercase alphabetic characters.
输入由一条或多条邮递路线构成。路线由一系列的街道名称(字符串)来表示,每条街独占一行。字符串“deadend”表示一条路线的结束,但它本身不是路线的一部分。每条街道的第一个和最后一个字母代表了这条街道的两个路口,街道名称的长度即为穿过这条街道所需的开销。所有街道的名称都由小写字母构成。
For example, the name foo indicates a street with intersections f and o of length 3, and the name computer indicates a street with intersections c and r of length 8. No street name will have the same first and last letter and there will be at most one street directly connecting any two intersections. As specified, the number of intersections with odd degree in a postal route will be at most two. In each postal route there will be a path between all intersections, i.e., the intersections are connected.
比如说,一条街道的名称为“foo”表示它的两个路口为“f”和“o”,且长度为3;另一条街道的名称为“computer”表示它的两个路口为“c”和“r”,长度为8。不存在首尾字母相同的街道,两个路口最多由一条街道直接连通。在每条邮递路线中都存在一条路径可以跑遍所有的路口,即所有路口都是连通的。

Output

For each postal route the output should consist of the cost of the minimal tour that visits all streets at least once. The minimal tour costs should be output in the order corresponding to the input postal routes.
  对应输入的每条邮递路线,应输出访问其所有街道至少一次的最短路径的开销。最短路径开销应按照输入的邮递路线的相应顺序输出。

Sample Input

one
two
three
deadend
mit
dartmouth
linkoping
tasmania
york
emory
cornell
duke
kaunas
hildesheim
concord
arkansas
williams
glasgow
deadend
 

Sample Output

11
114
 
 
 

按题目的定义,可将十字路口视为节点,街道视为节点之间的边,那么所给出的数据就是一个强连通无向图(即任何边都可正反两个方向通过,且不存在无法到达的节点)。此外题目中还给出奇数度的路口数最多为2,奇顶点的数目等于0或2。

所有街道只走一次就可以走完所有街道。根据欧拉回路的充要条件可知,如果图中只有偶顶点,那么必然存在一条从起点出发,走完全部街道后返回原点的路线。如果存在奇顶点,那么要一遍走完所有街道则必须从其中一个奇顶点出发,到另一个奇顶点结束。这样题目的思路就很清晰了。先将所有街道的长度和作为最短路径长度,如果存在奇顶点路口,还要加上两个奇顶点之间的最短路径。这道题的规模很小,最多26个路口,因此使用复杂度为O(n3)的弗洛伊德算法(维基百科)来解决最短路径问题是非常便捷的。

 
 #include <iostream>
#include <string.h>
#include <string>
using namespace std;
int map[26][26],deg[26],odd[5];
int main()
{
    string name;
    int sum=0;
    while(cin>>name)
    {
        int flag=1;
        if(name=="deadend")
            flag=0;
        if(flag)
        {
            int len=name.size();
            int u=name[0]-'a';
            int v=name[len-1]-'a';
            deg[u]++;  deg[v]++;
            map[u][v]=map[v][u]=len;
            sum=sum+len;
            continue;
        }
        int i,j,k=0;
        for(i=0;i<26;i++)
            if(deg[i]%2==1)
               odd[k++]=i;
        if(k==0)
            cout<<sum<<endl;
        else
        {
            for(k=0;k<26;k++)
              for(i=0;i<26;i++)
                for(j=0;j<26;j++)
                 if(map[i][k]>0&&map[k][j]>0)
                 {
                     if(map[i][j]>0)
                     {
                         if(map[i][j]>map[i][k]+map[k][j])
                             map[i][j]=map[i][k]+map[k][j];
                     }
                     else
                        map[i][j]=map[i][k]+map[k][j];
                 }
            sum=sum+map[odd[0]][odd[1]];
            cout<<sum<<endl;
        }
        sum=0;
        memset(map,0,sizeof(map));
        memset(deg,0,sizeof(deg));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值