[Islands and Bridges] Problem solving

topic

Topic description

Given some islands and some bridges connecting the islands, we all know that Hamilton Road is a route to visit each island once. In our map, each island has a positive integer weight, which represents the viewing value of the island. Assuming a total of N islands, the value of the island Ci is represented by Vi, and the value of the Hamilton Road C1C2....Cn is the sum of the following three parts:
  (1) The sum of the values ​​of all islands;
  (2) For adjacent roads in the path (3) There are three consecutive islands CiCi+ 1Ci
  +2 in the path. If Ci and Ci+2 are directly connected by a bridge, then add The product of these three island values ​​is added to the total value.
  Ask to calculate the maximum value of Hamilton Road and the number of options.

enter

The first line of input is an integer Q (Q<=20), which represents the number of test data. In the first line of each test data, input two integers N and M, which represent the number of islands and bridges respectively, the next line contains N positive integers, the i-th number represents Vi, each number does not exceed 100, and the last M line, There are two numbers X, Y in each line, indicating that there is a bridge directly connected between island X and island Y, the bridge is bidirectional, and the islands are numbered from 1 to N (N<=13)

output

For each test data, output one line, two integers, the first number represents the maximum value, the second number represents the number of solutions, if there is no Hamiltonian path, output "0 0"
Note: a path can be reversed, we Consider the two paths to be the same path.

sample input

2
3 3
2 2 2
1 2
2 3
3 1
4 6
1 2 3 4
1 2
1 3
1 4
2 3
2 4
3 4

Sample output

22 3
69 1

analyze

For the first question, because N<=13, we can use the state to compress dp and compress the state of whether each point has passed; when there are three consecutive islands in the path, CiCi+1Ci+2, there is a bridge between Ci and Ci+2. When connecting, you need to know the two points Ci and Ci+1. So the dp equation is f[i][j][k], which means that when in state i, it has reached point k, and the last point reached is the maximum value of j. The dp equation shifts to:

f[i+bb[l]][k][l]=max(f[i+bb[l]][k][l],f[i][j][k]+v[k] v [l]+v[l]) //The bb array stores 2^i
f[i+bb[l]][k][l]=max(f[i+bb[l]][k][l] ,f[i][j][k]+v[k]
v[l]+v[j] v[k] v[l]+v[l])
//j and l have the same path

For the second question, because the number of solutions that require the greatest value, g[i][j][k] is used to refer to the point k when you are in state i, and the last point you went to is the maximum value of j number of plans. Overwrite answer if transferable but not equal, accumulate answer only if transferable and equal. Finally, count the number of solutions when the value is the largest.

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
long long g[10001][20][20],f[10001][20][20];
long long n,m,e,v[30];
long long bb[30];
bool b[30][30];
int main()
{
    cin>>e;
    long long x,y;
    bb[1]=1;
    int i,j,k,l;
    for(i=2;i<=29;i++)
        bb[i]=bb[i-1]*2;
    while(e--)
    {
        scanf("%lld%lld",&n,&m);
        for(i=0;i<=10000;i++)
            for(j=0;j<=19;j++)
                for(k=0;k<=19;k++)
                {
                    f[i][j][k]=0;
                    g[i][j][k]=0;
                }
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
            {
                b[i][j]=false;
            }
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&v[i]);
        }
        for(i=1;i<=m;i++)
        {
            scanf("%lld%lld",&x,&y);
            b[x][y]=b[y][x]=true;
            f[bb[x]+bb[y]][x][y]=f[bb[x]+bb[y]][y][x]=v[x]*v[y]+v[x]+v[y];//初始化f数组
            g[bb[x]+bb[y]][x][y]=g[bb[x]+bb[y]][y][x]=1;//初始化g数组
        }
        for(i=0;i<=bb[n+1]-1;i++)
        {
            for(j=1;j<=n;j++)
                if((bb[j] | i)==i)        
                    for(k=1;k<=n;k++)
                        if((bb[k] | i)==i && b[j][k]){if(!g[i][j][k]) continue;
                            for(l=1;l<=n;l++)
                                if((bb[l] | i)!=i && b[k][l] && b[j][l])//当j和l有路径相同
                                {
                                    if(f[i+bb[l]][k][l]==f[i][j][k]+v[k]*v[l]+v[j]*v[k]*v[l]+v[l])
                                        g[i+bb[l]][k][l]+=g[i][j][k];
                                    else
                                    //当j和l无路径相同
                                    if(f[i+bb[l]][k][l]<f[i][j][k]+v[k]*v[l]+v[j]*v[k]*v[l]+v[l])
                                    {
                                        f[i+bb[l]][k][l]=f[i][j][k]+v[k]*v[l]+v[j]*v[k]*v[l]+v[l];
                                        g[i+bb[l]][k][l]=g[i][j][k];
                                    }
                                }
                                else
                                if((bb[l] | i)!=i && b[k][l])
                                {
                                    if(f[i+bb[l]][k][l]==f[i][j][k]+v[k]*v[l]+v[l])
                                        g[i+bb[l]][k][l]+=g[i][j][k];
                                    else
                                    if(f[i+bb[l]][k][l]<f[i][j][k]+v[k]*v[l]+v[l])
                                    {
                                        f[i+bb[l]][k][l]=f[i][j][k]+v[k]*v[l]+v[l];
                                        g[i+bb[l]][k][l]=g[i][j][k];
                                    }
                                }}
        }
        long long ans=0;
        long long ma=0;
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                if(f[bb[n+1]-1][i][j]>ma)
                {
                    ma=f[bb[n+1]-1][i][j];
                    ans=g[bb[n+1]-1][i][j];
                }
                else
                if(f[bb[n+1]-1][i][j]==ma)
                {
                    ans+=g[bb[n+1]-1][i][j];
                }
            }
        if(n==1) cout<<v[1]<<' '<<1<<endl;else
        if(ma==0 || ans==0) cout<<0<<' '<<0<<endl;else
        printf("%lld %lld\n",ma,ans/2);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325281659&siteId=291194637