LightOJ 1086 Jogging Trails(记忆化搜索)

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

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

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

 

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 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<<n)-1) return 0;

31     if(f[st]!=-1) return f[st];

32     f[st]=INF;

33     int i,j,st0;

34     for(i=0;i<n;i++) if(!(st&(1<<i))) for(j=i+1;j<n;j++) if(!(st&(1<<j)))

35     {

36         st0=st|(1<<i)|(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 }

 

 

 

你可能感兴趣的:(Rails)