poj2404

题意:给定一张图,要求从起点出发走遍每一条边并回到起点的最短路径。。

思路:由一笔画问题可知,想满足题意每个点必须是偶点(度为偶数),所以首先用floyed做一遍最短路,

         找到奇点之间的最短路径。。

         接下来便是用状态压缩dp就可决解。。

   

 1 /*
 2   State:Accepted
 3   Time:2013-03-21 14:50:26
 4 */
 5 #include<cstdio>
 6 #include<cstdlib>
 7 #include<fstream>
 8 #include<queue>
 9 #include<stack>
10 #include<algorithm>
11 #include<vector>
12 #include<list>
13 #include<set>
14 #include<string>
15 #include<cstring>
16 #include<map>
17 #include<cmath>
18 #include<iostream>
19 #define M0(NAME) memset(NAME, 0 , sizeof(NAME))
20 using namespace std;
21 const int maxn = 1 << 15;
22 int f[maxn + 10],  a[21][21] , n , m ,ans , du[21] ,opt;
23 
24 void init(){
25      int x , y ,z;
26      M0(du);
27      M0(f);
28      ans = 0;
29      scanf("%d",&m);
30      for (int i = 1; i <= 20; ++i)
31           for (int j = 1; j <= 20; ++j)
32                a[i][j] = 0xfffffff;
33      for (int i = 0; i < m; ++i){
34             scanf("%d%d%d", &x, &y ,&z); 
35             if (z < a[x][y])
36                 a[x][y] = a[y][x] = z;
37             
38             ans += z;
39             ++du[x];
40             ++du[y];
41             
42      }    
43 }
44 
45 void floyed(){
46     for (int k = 1; k <= n; ++k)
47        for  (int i = 1; i <= n; ++i)
48          for  (int j = 1; j <= n; ++j){
49                   if (i == j || j == k || i == k) continue;
50                   a[i][j] = min(a[i][j] , a[i][k] + a[k][j]);    
51         }     
52 }
53 
54 
55 int dfs(int opt){
56      if (opt == 0) return 0;
57      if (f[opt]>0) return f[opt];
58      int tm = 0xfffffff, temp;
59      for (int i = 1; i < n; ++i)
60          if (1<< i-1 & opt)
61          for (int j = i + 1; j <= n; ++j)
62             if  (1<< j-1 & opt){
63                     temp = dfs(opt - (1 << i - 1) - (1 << j - 1)) + a[i][j];
64                     tm = min(tm ,temp);
65             }
66      return f[opt] = tm;
67     
68 }
69 int main(){
70     freopen("poj2404.in","r",stdin); 
71     freopen("poj2404.out","w",stdout);
72     while (~scanf("%d", &n) && n){
73           init();
74           floyed();
75           opt = 0;
76           for (int i = 1; i <= n; ++i)
77                  if (du[i] % 2 == 1) opt |= (1 << i - 1);
78           ans += dfs(opt);
79           printf("%d\n",ans);
80     }
81     
82     return 0;
83 }

 

posted on 2013-03-24 00:48  yzcstc  阅读(271)  评论(0编辑  收藏  举报