COJ 1175 A Tour Around Hangzhou (最短路+状态压缩DP)

模型:给一个n个点的无向带权图,求从指定起点出发,经过指定的k个点(顺序不定)最后回到起点的最小代价。

数据范围:n<=10^4, m<=10^5, k<15

分析:先求最短路,求出从指定的k+1(含起点)个点到其他点的最小代价,然后建立k+1个点之间的最小代价邻接矩阵。最后用状态压缩DP求结果(状态压缩DP参考上一篇)。

View Code
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define MIN(a,b) ((a)<(b)?(a):(b))
#define INF 0x3f3f3f3f
#define N 10010
#define M 200010
#define K 15
int n,m,k,e;
int first[N],next[M],v[M],w[M];
int id[K];
int d[K][N];
bool inq[N];

int g[K][K];
int dp[1<<K][K];

void init()
{
    e=0;
    memset(first,-1,sizeof(first));
}
void add(int a,int b,int c)
{
    v[e]=b;
    w[e]=c;
    next[e]=first[a];
    first[a]=e++;
}
void spfa(int i)
{
    int a,b,j;
    a=id[i];
    queue<int>q;

    memset(inq,0,sizeof(inq));
    memset(d[i],0x3f,sizeof(d[i]));
    d[i][a]=0;

    q.push(a);
    inq[a]=1;

    while(!q.empty())
    {
        a=q.front(),q.pop();
        inq[a]=0;

        for(j=first[a];j!=-1;j=next[j])
        {
            b=v[j];
            if(d[i][b]>d[i][a]+w[j])
            {
                d[i][b]=d[i][a]+w[j];
                if(!inq[b]) inq[b]=1,q.push(b);
            }
        }
    }
}
int DP(int s,int last)
{
    if(dp[s][last]!=-1) return dp[s][last];

    int ns=s^(1<<last);
    if(ns==1)   return g[0][last];

    int ret=INF;
    for(int i=1;i<k;i++)    if((ns>>i)&1)
    {
        ret=MIN(ret,DP(ns,i)+g[i][last]);
    }
    return dp[s][last]=ret;
}
int main()
{
    int i,j,a,b,c;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        init();
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        k++;
        for(i=0;i<k;i++)
        {
            scanf("%d",&id[i]);
            spfa(i);
        }
        for(i=0;i<k;i++)
        {
            for(j=0;j<k;j++)
            {
                g[i][j]=d[i][id[j]];
            }
        }
        int ans=INF;
        memset(dp,-1,sizeof(dp));
        for(i=0;i<k;i++)
        {
            ans=MIN(ans,DP((1<<k)-1,i)+g[0][i]);
        }
        if(ans<INF) printf("%d\n",ans);
        else    puts("What a pity");
    }
    return 0;
}

 

posted @ 2012-08-05 09:49  BeatLJ  阅读(311)  评论(0编辑  收藏  举报