LightOJ 1086 Jogging Trails(记忆化搜索)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1086

题意:给出n个顶点m条边的无向图。从其中某个顶点出发将每条边遍历至少一次回到出发点。求最短路。

思路:欧拉回路的每个点的度必为偶数。所以只要将所有度数为奇数的点找出,将其两两之间的最短路求出,状态压缩记忆化搜索即可。度数为奇数的点必为偶数个。因为每条边连两个顶点,所以所有点的总度数为偶数,假设奇度的点有x个,则偶度得点n-x个,可以x必为偶数。所以只要在奇度点之间每两个连一条边即可。

 

View Code
 1 #include 
 2 #include 
 3 #include 
 4 #define min(x,y) ((x)<(y)?(x):(y))
 5 using namespace std;
 6 
 7 const int INF=1000000000;
 8 int C,num=0;
 9 int a[20][20],sum,f[(1<<16)+5],deg[20],b[20][20];
10 int n,m;
11 
12 void init()
13 {
14     int i,j,k;
15     for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++)
16        a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
17     int temp[20],num=0,u,v;
18     for(i=1;i<=n;i++) if(deg[i]&1) temp[++num]=i;
19     for(i=1;i<=num;i++) for(j=1;j<=num;j++)
20     {
21         u=temp[i];
22         v=temp[j];
23         b[i-1][j-1]=a[u][v];
24     }
25     n=num;
26 }
27 
28 int DFS(int st)
29 {
30     if(st==(1<1) return 0;
31     if(f[st]!=-1) return f[st];
32     f[st]=INF;
33     int i,j,st0;
34     for(i=0;iif(!(st&(1<for(j=i+1;jif(!(st&(1<<j)))
35     {
36         st0=st|(1<1<<j);
37         f[st]=min(f[st],b[i][j]+DFS(st0));
38     }
39     return f[st];
40 }
41 
42 int main()
43 {
44     for(scanf("%d",&C);C--;)
45     {
46         scanf("%d%d",&n,&m);
47         sum=0;
48         int i,j,u,v,w;
49         for(i=1;i<=n;i++)
50         {
51             for(j=1;j<=n;j++) a[i][j]=INF;
52             a[i][i]=0;
53         }
54         memset(deg,0,sizeof(deg));
55         for(i=1;i<=m;i++)
56         {
57             scanf("%d%d%d",&u,&v,&w);
58             a[u][v]=a[v][u]=min(a[u][v],w);
59             deg[u]++;
60             deg[v]++;
61             sum+=w;
62         }
63         init();
64         memset(f,-1,sizeof(f));
65         printf("Case %d: %d\n",++num,sum+DFS(0));
66     }
67     return 0;
68 }

 

 

 

你可能感兴趣的:(LightOJ 1086 Jogging Trails(记忆化搜索))