Sightseeing trip

Time Limit: 1000MS

 

Memory Limit: 65536K

Total Submissions: 6491

 

Accepted: 2486

 

Special Judge

Description

There is a travel agency in Adelton town on Zanzibar island. It has decided to offer its clients, besides many other attractions, sightseeing the town. To earn as much as possible from this attraction, the agency has accepted a shrewd decision: it is necessary to find the shortest route which begins and ends at the same place. Your task is to write a program which finds such a route. 

In the town there are N crossing points numbered from 1 to N and M two-way roads numbered from 1 to M. Two crossing points can be connected by multiple roads, but no road connects a crossing point with itself. Each sightseeing route is a sequence of road numbers y_1, ..., y_k, k>2. The road y_i (1<=i<=k-1) connects crossing points x_i and x_{i+1}, the road y_k connects crossing points x_k and x_1. All the numbers x_1,...,x_k should be different.The length of the sightseeing route is the sum of the lengths of all roads on the sightseeing route, i.e. L(y_1)+L(y_2)+...+L(y_k) where L(y_i) is the length of the road y_i (1<=i<=k). Your program has to find such a sightseeing route, the length of which is minimal, or to specify that it is not possible,because there is no sightseeing route in the town.

Input

The first line of input contains two positive integers: the number of crossing points N<=100 and the number of roads M<=10000. Each of the next M lines describes one road. It contains 3 positive integers: the number of its first crossing point, the number of the second one, and the length of the road (a positive integer less than 500).

Output

There is only one line in output. It contains either a string 'No solution.' in case there isn't any sightseeing route, or it contains the numbers of all crossing points on the shortest sightseeing route in the order how to pass them (i.e. the numbers x_1 to x_k from our definition of a sightseeing route), separated by single spaces. If there are multiple sightseeing routes of the minimal length, you can output any one of them.

Sample Input

5 7
1 4 1
1 3 300
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20

Sample Output

1 3 5 2

Source

​CEOI 1999​

题目大意:n个点,m条边的加权无向图,求其中的最小环,并输出路径

在Adelton城有一个桑给巴尔岛的旅行社。它已决定提供它的客户,其中一些景点,观光小镇。为了赚取尽可能多的钱,该机构接受了一个精明的决定:有必要找到最短的路线,开始和结束在同一个地方。你的任务是写一个程序,找到这样的路线。

镇上有n个景点,编号从1到N和M个双向道路编号从1到M。

两个景点可以通过多条道路连接,但没有道路连接本身景点。每一条观光路线是一个有序的道路编号,道路数k大于2。观光路线是无重复景点的环路。观光路线的长度是所有路线长度之和。您的程序必须找到长度最小的观光路线,或指定它是不可能的。

输入:第一行包含两个正整数:景点个数N<=100,道路个数M<=10000。

以下M行,每行包含3个正整数:表示道路两个景点的编号和道路长度(小于500)。

输出:输出只有一行。如果没有观光路线输出“No solution.”,或按路径顺序给出最短观光路线,用空格隔开。如果有多个最小长度的观光路线,你可以输出任何一个。

 

1 #include "bits/stdc++.h"
2 #define mem(a,b) memset(a,b,sizeof(a))
3 using namespace std;
4 typedef long long LL;
5 const int MAX=105;
6 const int oo=100000000;
7 int n,m;
8 int dist[MAX][MAX],a[MAX][MAX];
9 int pre[MAX][MAX];
10 int ans[MAX];
11 int loop;
12 inline int mn(int x,int y){return x<y?x:y;}
13 inline int mx(int x,int y){return x>y?x:y;}
14 void init(){
15 int i,j;
16 int u,v,w;
17 for (i=1;i<=n;i++) for (j=1;j<=n;j++) dist[i][j]=a[i][j]=(i==j?0:oo);
18 mem(pre,0);
19 ans[0]=0;
20 for (i=1;i<=m;i++){
21 scanf("%d%d%d",&u,&v,&w);
22 a[u][v]=mn(a[u][v],w);
23 dist[u][v]=dist[v][u]=a[v][u]=a[u][v];
24 }
25 }
26 void dfs(int u,int v){
27 int k=pre[u][v];
28 if (k==0){
29 ans[++ans[0]]=v;
30 return;
31 }
32 dfs(u,k);
33 dfs(k,v);
34 }
35 void floyd(){
36 int i,j,k;
37 loop=oo;
38 for (k=1;k<=n;k++){
39 for (i=1;i<k;i++){
40 for (j=i+1;j<k;j++){
41 if (dist[i][j]+a[i][k]+a[k][j]<loop){
42 loop=dist[i][j]+a[i][k]+a[k][j];
43 ans[0]=0;
44 ans[++ans[0]]=i;
45 dfs(i,j);
46 ans[++ans[0]]=k;
47 }
48 }
49 }
50 for (i=1;i<=n;i++){
51 for (j=1;j<=n;j++){
52 if (dist[i][j]>dist[i][k]+dist[k][j]){
53 pre[i][j]=k;
54 dist[i][j]=dist[i][k]+dist[k][j];
55 }
56 }
57 }
58 }
59 }
60 int main(){
61 freopen ("trip.in","r",stdin);
62 freopen ("trip.out","w",stdout);
63 init();int i,j;
64 while (~scanf("%d%d",&n,&m)){
65 init();
66 floyd();
67 if (loop==oo)
68 puts("No solution.");
69 else{
70 for (i=1;i<ans[0];i++)
71 printf("%d ",ans[i]);
72 printf("%d\n",ans[i]);
73 }
74 }
75 return 0;
76