• 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
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    解决方法:未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序
    解决装系统选中的磁盘采用的是GPT分区形式
    破解windows server 2008 的登录密码。有效的
    Arcgis Engine(ae)接口详解(8):临时元素(element)
    Arcgis Engine(ae)接口详解(7):地图(map)操作
    Arcgis Engine(ae)接口详解(5):IGeometry几何高级操作
    Arcgis Engine(ae)接口详解(6):workspace操作
    Arcgis Engine(ae)接口详解(5):IGeometry几何基础操作
    Arcgis Engine(ae)接口详解(3):featureClass的feature编辑和删除
    Arcgis Engine(ae)接口详解(4):featureClass的feature插入
  • 原文地址:https://www.cnblogs.com/starve/p/13762121.html
Copyright © 2020-2023  润新知