• 逛公园题解


    这道题是noip2017原题。

    首先,首先你可以思考一下,第一天dp不见了。似乎有很多人这么说。那么前两道题 我猜的 显然不是DP,所以说这道题可以用DP解。

    但是我用的方法是记忆化搜索。因为DP这个东西 我太蒻了,不会  没有记忆化优美。

    具体做法是跑一次反向的最短路,令f[u][k] 表示 dis(u,n)<=MinDis(u,n)+k的方案数,答案就是 f[1][K]。(从1号点到n好点不超过k的方案数)

    考虑边(u,v,w)。

    如果走这条边的话, dis(v,n)=MinDis(v,n)+w-MinDis(u,n) f[u][k]=f[v][k(MinDis(v,n)MinDis(u,n)+w)]

    这样怎么判 0 环呢?只要加个标记判断一下就可以了。

    还有一点要注意,就是必须先写一个函数判0环,再求值。不然的话可能会玄学死循环。

    还有,就是f初值必须是1,赋值成0可能会原地爆炸。

    代码实现:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<climits>
    #define int long long
    #define maxa 400005
    #define mem(x) memset(x,0,sizeof(x))
    #define mp(a,b) make_pair(a,b)
    using namespace std;
    void read(int &x){
        x=0;
        char c=getchar();
        while(c<'0'||c>'9'){
            c=getchar();
        }
        while(c<='9'&&c>='0'){
            x=((x<<1)+(x<<3))+c-48;
            c=getchar();
        }
        return ;
    }
    
    int n,m,k,mod;
    int to[maxa],nxt[maxa],h[maxa],top,val[maxa];
    int To[maxa],Nxt[maxa],H[maxa],Top,Val[maxa];
    void psh(int u,int v,int va){
        to[++top]=v,nxt[top]=h[u],h[u]=top,val[top]=va;
        To[++Top]=u,Nxt[Top]=H[v],H[v]=Top,Val[Top]=va;
        return ;
    }
    
    int dis[maxa],vis[maxa];
    void AC_DREAM(){//迪杰斯特拉
        priority_queue <pair<int,int>,vector<pair<int,int> >,greater <pair<int,int> > >q ;
        q.push(mp(0,1));
        while(!q.empty()){
            int now=q.top().second;q.pop();
            if(vis[now])continue;
            vis[now]=1;
            for(register int i=h[now];i;i=nxt[i]){
                int y=to[i];
                if(dis[y]>dis[now]+val[i])dis[y]=dis[now]+val[i],q.push(mp(dis[y],y));
            }
        }
        return ;
    }
    int dp[maxa][51];
    int bl[maxa][51];
    bool yy;
    int num,y;
    int dfs(int x,int kk){//一定要写两遍,反正差不多,复制一下改一改就可以了。。。
        if(~dp[x][kk])return dp[x][kk];
        bl[x][kk]=1,dp[x][kk]=0;
        for(register int i=H[x];i;i=Nxt[i]){
            y=To[i];
            num=dis[x]-dis[y]+kk-Val[i];
            if(num<0)continue;
            dp[x][kk]=(dp[x][kk]+dfs(y,num))%mod;
        }
        bl[x][kk]=0;
        return dp[x][kk];
    }
    void dfs1(int x,int kk){//非常重要,必须分开写,不然玄学TLE
        if(yy)return ;
        if(~dp[x][kk])return ;
        bl[x][kk]=1,dp[x][kk]=0;
        for(register int i=H[x];i;i=Nxt[i]){
            y=To[i];
            num=dis[x]-dis[y]+kk-Val[i];
            if(num<0)continue;
            if(bl[y][num]){
                yy=1;
                return ;
            }
            dfs1(y,num);
            
        }
        bl[x][kk]=0;
        return ;
    }
    void clear(){
        yy=Top=top=0;
        mem(to),mem(nxt),mem(h),mem(val);
        mem(To),mem(Nxt),mem(H),mem(Val);
        
        mem(vis);
        for(register int i=2;i<=n;i++)dis[i]=1000000000;
        
        mem(bl);
        
    }
    
    
    #undef int
    int main(){
        #define int long long
        int T;
        read(T);
        while(T--){
            read(n),read(m),read(k),read(mod);
            clear();
            for(register int i=1,u,v,va;i<=m;i++){
                read(u),read(v),read(va);
                psh(u,v,va);
            }
            AC_DREAM();
    //        for(int i=1;i<=top;i++)cout<<dis[i]<<" ";
    //        cout<<endl;
            mem(vis);
            int ans=0;
            memset(dp,-1,sizeof(dp));//一定要赋值成-1!
            for(register int i=0;i<=k;i++)dfs1(n,i);
            if(yy){
                cout<<-1<<endl;
                continue;
            }
            memset(dp,-1,sizeof(dp));//一定要赋值成-1!
            dp[1][0]=1;
            for(register int i=0;i<=k;i++)ans=(ans+dfs(n,i))%mod;
            cout<<ans<<endl;
        }
        
    }
  • 相关阅读:
    net中System.Security.Cryptography 命名空间 下的加密算法
    关于如何生成代码的帮助文档的链接
    Application.EnableVisualStyles();
    VS2010里属性窗口中的生成操作
    把普通的git库变成bare库
    MultiTouch camera controls source code
    android onTouch()与onTouchEvent()的区别
    iOS开发中常见的语句@synthesize obj = _obj 的意义详解
    java nio 快速read大文件
    使用ndk standalone工具链来编译某个平台下的库
  • 原文地址:https://www.cnblogs.com/WQT-FFT/p/11406499.html
Copyright © 2020-2023  润新知