题目:http://acm.hdu.edu.cn/showproblem.php?pid=5418
分析:Floyd出任两个国家之间最短距离,然后DP。f[S][i]表示访问状态为S且最后一个访问的为i的最小值。则f[S|(1<<(i-1))][i]=min(f[S][j]+dist[i][j]) 其中S&(1<<(j-1))>0且ij连通。
答案即。所以时间复杂度:O[n^3+(2^n)*(n^2)]
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int Tmax=20,inf=0x3f3f3f3f;
int n,m,dist[Tmax][Tmax],f[131075][Tmax],ans;
bool G[Tmax][Tmax];
void work()
{
int i,S,j,smax=1<<n;
f[1][1]=0;
for(S=1;S<smax;S++)
for(i=1;i<=n;i++)
if((S&(1<<(i-1)))==0)
for(j=1;j<=n;j++)
if((S&(1<<(j-1)))>0)
f[S|(1<<(i-1))][i]=min(f[S|(1<<(i-1))][i],f[S][j]+dist[i][j]);
for(i=1;i<=n;i++)
ans=min(ans,f[smax-1][i]+dist[i][1]);
printf("%d\n",ans);
return;
}
void floyd()
{
int i,j,k;
for(i=1;i<=n;i++) dist[i][i]=0;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(dist[i][k]>=0&&dist[k][j]>=0)
{
if(dist[i][j]==-1) dist[i][j]=dist[i][k]+dist[k][j];
else dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
}
return;
}
void init()
{
memset(G,0,sizeof(G));
memset(dist,-1,sizeof(dist));
for(int i=1;i<=(1<<n);i++) for(int j=1;j<=n;j++) f[i][j]=inf;
ans=2147483647;
return;
}
int main()
{
int T,i,u,v,w;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
init();
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&u,&v,&w);
G[u][v]=G[v][u]=true;
dist[u][v]=dist[v][u]=(dist[u][v]==-1?w:min(dist[u][v],w));
}
floyd();
work();
}
return 0;
}