【最小环】Sightseeing Trip

来源:互联网 发布:怎么登陆支付宝知托付 编辑:程序博客网 时间:2024/06/04 20:50

Ural 1004 ,很简单的题,但是测试要求很BT我觉得


Translate:URAL/1004

Sightseeing trip 观光旅游Time Limit: 2 secondMemory Limit: 16M


目录

 [隐藏] 
  • 1Background
  • 2Problem
  • 3Input
  • 4Output
  • 5Sample Input
  • 6Sample Output

[编辑]Background

在桑给巴尔岛的Adelton城镇上有一个旅游机构。城镇里有许多景点,于是它们决定为其客户提供游览这些景点的服务。为了从这些景点中尽可能获利,这个旅游机构通过了一个精明决定:必须找一条起点与终点相同的最短路线。

[编辑]Problem

你的任务是编写一条程序来找类似的的一条路线。在这个镇上,有N个十字路口(编号1至N),两个十字路口之间可以有多条道路连接,有M条双向行驶的道路(编号为1至M)。但没有一条道路从一个十字路口出发又回到同一个路口。每一条观光路线都是由一 些路组成的,这些道路序号是:y_1, ..., y_k,且k>2。第y_i(1<=i<=k-1)号路是连接第x_i号十字路口和第x_{i+1}号十字路口的;其中第y_k号路是连接第x_k号十字路口和第x_1号十字路口。而且所有的这些x_1,...,x_k分别代表不同路口的序号。在 某一条观光路线上所有道路的长度的和就是这条观光路线的总长度。换言之L(y_1)+L(y_2)+...+L(y_k) 的和 L(y_i)就是第y_i 号观光路线的长度。你的程序必须找出类似的一条路线:长度必须最小,或者说明在这个城镇上不存在这条观光路线。

[编辑]Input

含几组测试数据。每一组数据的第一行包含两个正整数:十字路口的个数N(N<=100),另一个是道路的 数目M(M<10000)。接下来的每一行描述一条路:每一行有三个正整数:这条路连接的两个路口的编号,以及这条路的长度(小于500的正整数)。最后以`-1`结束。


[编辑]Output

每一行输出都是一个答案。如果这条观光路线是不存在的话就显示“No solution.”(PS:有句点);或者输出这条最短路线的经过所有十字 路口的序号,每一个序号之间用一个空格符隔开,这样更能说明这条路线是如何得出来的。也就是用从x_1到x_k描述一条观光路线。假如满足最短长度的观光路线不止一条,输出其中的任一条即可。

[编辑]Sample Input

5 71 4 11 3 3003 1 101 2 162 3 1002 5 155 3 204 31 2 101 3 201 4 30-1

[编辑]Sample Output

1 3 5 2No solution.


就是一个Floyd求最小环。基本代码不用讲,求最小环的原理很简单,可以参见Wikipedia的证明。

记录方案有很多方法,Wzz跟我讲过迭代加深的方法,但是没有听懂。。

我的方法是最容易理解的,但是有一个地方很容易打错,应该是很多人都遭过的,上网看题解的时候,很多人都提到过这个地方。可是我还是错了,调了一天才发现是这里有问题

一定要注意,虽然最小环和最短路是双进程DP,但是这两个是紧密相关的,不能独立对待。因此可以考虑这样一种情况:

(虚线表示路,实线和虚线加起来表示环)


当某一时刻找到了A+b这一个最小环,此时我们g数组中记录下了甲乙之间最短路的中转点。

后来,我们找到了另一条甲乙的最短路,假设此路经过点丙,因此此路可以更新最短路,但是不一定能更新最小环,因此g数组变了,但是最小环不能更新。

我们输出结果的时候,是根据g来输出的,但是g被更改了。因此必须在每次求得最小环的时候记录下当前的g!!!

输出的时候,用一个递归,模拟二分过程,每次找[l,m]和[m+1,r]这两个区间


接下来讲讲很坑爹的地方:


1、如果有哪一个变量不初始化,基本上就WA第一组了。

2、如果有哪一个数组不初始化,基本上就Crash第一组了。

3、如果行末多了空格,就不清楚能得几分了。


#include <cstdio>#define inf (0x7f7f7f7f)long f[110][110];long g2[110][110];long path[110][110];long f2[110][110];long bm[110][110];long print[110];long cnt = 0;long n;long m;long ans = 0x7f7f7f7f;long sta;long endd;long midd;void make_path(){    for (long i=1;i<n+1;i++)    {        for (long j=1;j<n+1;j++)        {            path[i][j] = g2[i][j];        }    }}void dp(){    for (long k=1; k<n+1; k++)    {        for (long i=1; i<k; i++)        {            if (i == k) continue;            for (long j=i+1; j<k; j++)            {                if (j==k || j==i) continue;                if (f2[j][i]<inf&&bm[i][k]<inf&&bm[k][j]<inf)                    if (ans > f2[j][i]+bm[i][k]+bm[k][j])                    {                        ans = f2[j][i]+bm[i][k]+bm[k][j];                        make_path();                        sta = i;                        endd = j;                        midd = k;                    }            }        }        for (long i=1; i<n+1; i++)        {            if (i==k) continue;            for (long j=1; j<n+1; j++)            {                if (j==i || j==k) continue;                {                    if (f2[i][k]<inf&&f2[k][j]<inf)                    {                        if (f2[i][j] > f2[i][k]+f2[k][j])                        {                            f2[i][j] = f2[i][k]+f2[k][j];                            g2[i][j] = k;                        }                    }                }            }        }    }}void output(long i,long j){    if (path[i][j] == 0) return;    output(i,path[i][j]);    print[++cnt] = path[i][j];    output(path[i][j],j);}int main(){    freopen("trip.in","r",stdin);    freopen("trip.out","w",stdout);    scanf("%ld",&n);    while (n!=-1)    {        scanf("%ld",&m);        //////////////////////////        //Initialization        /////////////////////////        cnt = sta = endd = midd = 0;        ans = 0x7f7f7f7f;        for (long i=1; i<n+1; i++)        {            print[i] = 0;            for (long j=1; j<n+1; j++)            {                g2[i][j] = 0;                path[i][j] = 0;                bm[i][j] = f[i][j] = f2[i][j] = inf;            }        }        ///////////////////////////////        for (long i=1; i<m+1; i++)        {            long x;long y;long l;            scanf("%ld%ld%ld",&x,&y,&l);            if (f2[x][y] > l) f2[x][y]=bm[x][y]=l;            if (f2[y][x] > l) f2[y][x]=bm[y][x]=l;        }        dp();        if (ans < inf)        {            print[++cnt] = sta;            output(sta,endd);            print[++cnt] = endd;            if (midd!=path[sta][endd])                print[++cnt] = midd;            for (long i=1;i<cnt;i++)            {                printf ("%ld ",print[i]);            }            printf("%ld\n",print[cnt]);        }        else            printf("No solution.\n");        scanf("%ld",&n);    }    return 0;}


原创粉丝点击