CHEAP DELIVERIES 给定k个路径求连续走完的最短路径(k<=18,)

题:https://ac.nowcoder.com/acm/contest/7818/B

题意:给定k个路径(s->t),在无向图上跑最短路径长度是多少?(n,m<=1e4,k<=18)

分析:

  • 在走完某个路径后到达路径的t,要重新选择一条路径的起点来保证答案最优,这个过程就相当于dp的过程;
  • k很小,我们可以对k进行状压,当第k-1位为1时,表示第k条路径已经走完,当然,当前状态是由哪条路径走来的也需要记录,所以开多一维dp记录状态的来源;
  • 转移过程就是把状态为1的转移给自身状态为0的;
  • 最短路就处理一下2*k个点开始的最短路;
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int mod=1e9+7;
const int M=1e6+6;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
struct qnode{
    int v;
    ll c;
    qnode(int _v=0,ll _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const{
     return c>r.c;
    }
};
struct Edge{
    int v;
    ll cost;
    Edge(int _v=0,ll _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[M];
bool vis[M];
ll dist[M];
void Dij(int n,int start){
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++)
        dist[i]=INF;
    priority_queue<qnode>que;
    while(!que.empty())que.pop();
    dist[start]=0;
    que.push(qnode(start,0));
    qnode tmp;
        while(!que.empty()){
             tmp=que.top();
              que.pop();
              int u=tmp.v;
              if(vis[u])continue;
               vis[u]=true;
            for(int i=0;i<E[u].size();i++){
                 int v=E[tmp.v][i].v;
                  int cost=E[u][i].cost;
                  if(!vis[v]&&dist[v]>dist[u]+cost){
                       dist[v]=dist[u]+cost;
                    que.push(qnode(v,dist[v]));

                }
            }
        }
}
void addedge(int u,int v,ll w){
    E[u].push_back(Edge(v,w));
}
const int N=1e4+4;
ll dis[40][N],dp[M][20];
int getid[N],tmp[N];
struct PP{
    int x,y;
}a[M];
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        int u,v;
        ll w;
        scanf("%d%d%lld",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }
    int tot=0;
    for(int i=1;i<=k;i++)
        scanf("%d%d",&a[i].x,&a[i].y),tmp[++tot]=a[i].x,tmp[++tot]=a[i].y;
    tot=unique(tmp+1,tmp+1+tot)-tmp-1;
    for(int i=1;i<=tot;i++){
        getid[tmp[i]]=i;
        Dij(n,tmp[i]);
        for(int j=1;j<=n;j++) dis[i][j]=dist[j];
    }

    memset(dp,0x3f,sizeof(dp));
    for(int i=0;i<k;i++) dp[1<<i][i]=dis[getid[a[i+1].x]][a[i+1].y];

    ll ans=INF;
    for(int i=1;i<(1<<k);i++)
        for(int j=0;j<k;j++)
            if(((1<<j)&i)==0){
                for(int l=0;l<k;l++){
                    if(((1<<l)&i))
                        dp[i|(1<<j)][j]=min(dp[i|(1<<j)][j],
                                       dp[i][l] + dis[getid[a[l+1].y]][a[j+1].x]
                                       + dis[getid[a[j+1].x]][a[j+1].y]);

                }
            }


    for(int i=0;i<k;i++)
        ans=min(ans,dp[(1<<k)-1][i]);
    if(ans==INF)
        puts("-1");
    else
        printf("%lld\n",ans);
    return 0;
}
View Code

 

posted @ 2020-10-02 17:01  starve_to_death  阅读(260)  评论(0编辑  收藏  举报