题意:给出n个点,m条边的无向图,给出每个点的点权,求点权和最小的哈密顿路径,相邻两个点要加上点权的乘积,形成环要加上环上的点权
哇,这个题wa了好多发,后来发现是因为存在一个特殊情况,即n==1时需要特判,哎,还是自己想的不周到
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<string> 2 #include<cstring> 3 #include<cstdio> 4 #include<iostream> 5 #include<vector> 6 #include<cmath> 7 #include<algorithm> 8 #include<queue> 9 using namespace std;//题意:给出n个点,m条边的无向图,给出每个点的点权,求点权和最小的哈密顿路径,相邻两个点要加上点权的乘积,形成环要加上环上的点权 10 typedef long long ll; 11 ll dp[15][15][1<<14]; 12 ll nums[15][15][1<<14]; 13 bool map[15][15]; 14 ll val[15]; 15 int n,m; 16 int main() 17 { 18 int i,j,T,k,l; 19 scanf("%d",&T); 20 while(T--) 21 { 22 scanf("%d%d",&n,&m); 23 ll add=0; 24 for(i=0;i<n;i++)scanf("%lld",&val[i]),add+=val[i]; 25 memset(map,0,sizeof(map)); 26 memset(nums,0,sizeof(nums)); 27 memset(dp,-1,sizeof(dp)); 28 while(m--) 29 { 30 int a,b; 31 scanf("%d%d",&a,&b); 32 a--,b--; 33 map[a][b]=map[b][a]=1; 34 } 35 if(n==1) 36 { 37 printf("%d 1\n",val[0]); 38 continue; 39 } 40 for(i=0;i<n;i++) 41 { 42 for(j=0;j<n;j++) 43 { 44 if(i==j)continue; 45 if(!map[i][j])continue; 46 dp[i][j][(1<<i)|(1<<j)]=val[i]*val[j]; 47 nums[i][j][(1<<i)|(1<<j)]=1; 48 } 49 } 50 for(i=0;i<(1<<n);i++) 51 { 52 for(j=0;j<n;j++)//back 53 { 54 if(i&(1<<j)==0)continue; 55 for(k=0;k<n;k++)//front 56 { 57 if(j==k)continue; 58 if(i&(1<<k)==0)continue; 59 if(nums[k][j][i]==0)continue; 60 if(dp[k][j][i]==-1)continue; 61 for(l=0;l<n;l++) 62 { 63 if(map[l][k]==0)continue; 64 if(l==j||l==k)continue; 65 if(i&(1<<l))continue; 66 ll gain=val[l]*val[k]; 67 if(map[l][j]) 68 { 69 gain+=val[l]*val[k]*val[j]; 70 } 71 int state=i|(1<<l); 72 if(dp[l][k][state]==dp[k][j][i]+gain) 73 { 74 nums[l][k][state]+=nums[k][j][i]; 75 } 76 else if(dp[l][k][state]<dp[k][j][i]+gain) 77 { 78 dp[l][k][state]=dp[k][j][i]+gain; 79 nums[l][k][state]=nums[k][j][i]; 80 } 81 } 82 } 83 } 84 } 85 ll num=0,ans=-1; 86 for(i=0;i<n;i++) 87 { 88 for(j=0;j<n;j++) 89 { 90 if(i==j||map[i][j]==0)continue; 91 if(!nums[i][j][(1<<n)-1])continue; 92 if(dp[i][j][(1<<n)-1]==-1)continue; 93 if(ans<dp[i][j][(1<<n)-1]) 94 { 95 ans=dp[i][j][(1<<n)-1]; 96 num=nums[i][j][(1<<n)-1]; 97 } 98 else if(ans==dp[i][j][(1<<n)-1]) 99 { 100 num+=nums[i][j][(1<<n)-1]; 101 } 102 } 103 } 104 if(ans==-1) 105 { 106 printf("0 0\n"); 107 continue; 108 } 109 printf("%lld %lld\n",ans+add,num/2); 110 } 111 112 }