zoukankan      html  css  js  c++  java
  • BZOJ 1097: [POI2007]旅游景点atr [DP 状压 最短路]

    传送门

    题意:

    一个无向图,从$1$到$n$,要求必须经过$2,3,...,k+1$,给出一些限制关系,要求在经过$v le k+1$之前必须经过$u le k+1$

    求最短路


    预处理出$1...k+1$到其他点的最短路

    然后$f[i][s]$表示当前在$i$已经经过的点的集合为$s$的最短路

    只考虑$1,2,...,k+1$就行了,

    注意$1$也要考虑,一个点可能经过多次

    然后实测dij比spfa快....我想试$pb\_ds$来着结果发现我的电脑上没有ext/pb_ds/priority_queue.hpp

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=2e4+5,M=2e5+5,K=22,S=(1<<20)+5,INF=1e9;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m,k,u,v,w;
    int need[K],f[K][S];
    int d[K][N];
    struct Edge{
        int v,w,ne;
    }e[M<<1];
    int cnt,h[N];
    inline void ins(int u,int v,int w){
        cnt++;
        e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt;
    }
    int q[N],head,tail,inq[N];
    inline void lop(int &x){if(x==N) x=1;else if(x==0) x=N-1;}
    void spfa(int s,int *d){
        head=tail=1;
        d[s]=0;inq[s]=1;
        q[tail++]=s;
        while(head!=tail){
            int u=q[head++];inq[u]=0;lop(head);
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v;
                if(d[v]>d[u]+e[i].w){
                    d[v]=d[u]+e[i].w;
                    if(!inq[v]){
                        inq[v]=1;
                        if(d[v]<d[q[head]]) head--,lop(head),q[head]=v;
                        else q[tail++]=v,lop(tail);
                    }
                }
            }
        }
    }
    int main(){
        freopen("in","r",stdin);
        n=read();m=read();k=read();
        for(int i=1;i<=m;i++) u=read(),v=read(),w=read(),ins(u,v,w);
        memset(d,127,sizeof(d));
        for(int i=1;i<=k+1;i++) spfa(i,d[i]);
        int c=read();
        while(c--) u=read()-2,v=read(),need[v]|=(1<<u);
    
        memset(f,-1,sizeof(f));
        int All=1<<k;
        f[1][0]=0;
        for(int s=0;s<All;s++) 
            for(int i=1;i<=k+1;i++) if(f[i][s]!=-1){
                for(int j=2;j<=k+1;j++) if(j!=i && (need[j]&s)==need[j] ){
                    int t=s|(1<<(j-2));
                    if(f[j][t]>f[i][s]+d[i][j] || f[j][t]==-1)
                        f[j][t]=f[i][s]+d[i][j];
                }
            }
        int ans=INF;
        for(int i=1;i<=k+1;i++) 
            if(f[i][All-1]!=-1) ans=min(ans,f[i][All-1]+d[i][n]);
        printf("%d",ans);
    }
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    using namespace std;
    #define pii pair<int,int>
    #define MP make_pair
    #define fir first
    #define sec second
    typedef long long ll;
    const int N=2e4+5,M=2e5+5,K=22,S=(1<<20)+5,INF=1e9;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m,k,u,v,w;
    int need[K],f[K][S];
    int d[K][N];
    struct Edge{
        int v,w,ne;
    }e[M<<1];
    int cnt,h[N];
    inline void ins(int u,int v,int w){
        cnt++;
        e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt;
    }
    
    priority_queue<pii,vector<pii>,greater<pii> > q;
    bool done[N];
    void dij(int s,int *d){
        for(int i=1;i<=n;i++) d[i]=INF,done[i]=0;
        d[s]=0;
        q.push(MP(d[s],s));
        while(!q.empty()){
            int u=q.top().sec;q.pop();
            if(done[u]) continue;done[u]=1;
            for(int i=h[u];i;i=e[i].ne)
                if(d[e[i].v]>d[u]+e[i].w){
                    d[e[i].v]=d[u]+e[i].w;
                    q.push(MP(d[e[i].v],e[i].v));
                }
        }
    }
    int main(){
        freopen("in","r",stdin);
        n=read();m=read();k=read();
        for(int i=1;i<=m;i++) u=read(),v=read(),w=read(),ins(u,v,w);
        memset(d,127,sizeof(d));
        for(int i=1;i<=k+1;i++) dij(i,d[i]);
        int c=read();
        while(c--) u=read()-2,v=read(),need[v]|=(1<<u);
    
        memset(f,-1,sizeof(f));
        int All=1<<k;
        f[1][0]=0;
        for(int s=0;s<All;s++) 
            for(int i=1;i<=k+1;i++) if(f[i][s]!=-1){
                for(int j=2;j<=k+1;j++) if(j!=i && (need[j]&s)==need[j] ){
                    int t=s|(1<<(j-2));
                    if(f[j][t]>f[i][s]+d[i][j] || f[j][t]==-1)
                        f[j][t]=f[i][s]+d[i][j];
                }
            }
        int ans=INF;
        for(int i=1;i<=k+1;i++) 
            if(f[i][All-1]!=-1) ans=min(ans,f[i][All-1]+d[i][n]);
        printf("%d",ans);
    }
  • 相关阅读:
    微信聊天框测试思路
    巧用&&和|| 让逻辑代码更简洁,逼格看起来更高一点(玩笑脸)
    获取URL中的参数
    解决移动端点击闪烁问题
    npm安装依赖包 --save-dev 和 --save; package.json的devDependencies和dependencies 的区别!
    vue-cli 3配置接口代理
    js小方法积累,将一个数组按照n个一份,分成若干数组
    web前端识别文字转语音
    html 锚点
    ES6 必须要用的数组Filter() 方法,不要再自己循环遍历了!!!
  • 原文地址:https://www.cnblogs.com/candy99/p/6512678.html
Copyright © 2011-2022 走看看