• 逛公园


    题目描述
    策策同学特别喜欢逛公园。公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边。其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。

    策策每天都会去逛公园,他总是从1号点进去,从N号点出来。

    策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到N号点的最短路长为d,那么策策只会喜欢长度不超过d+K的路线。

    策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?

    为避免输出过大,答案对P取模。

    如果有无穷多条合法的路线,请输出-1。

    解:
    思路很好想
    定义 f[i][j]表示以i号点为结尾的 距离起点距离为 dis+j j是偏量dis是最短距离 的方案数
    画个图可以知道 f[i][j]=(sum) $f[u][j-(dis[u]+le[s]-dis[i])] $ 可以利用记忆化搜索
    如果有0环则无解
    注意到我们tarjan求的是强连通分量 不是强连通子图
    所以我们可以建立边权为0的图求tarjan 求到的环一定满足充要条件
    注意判断这个环是否满足条件

    code:

    //
    #include<bits/stdc++.h>
    using namespace std;
    typedef  long long ll;
    #define maxnn 100005
    #define maxn 500005
    ll f[maxnn][55];
    #define inf 10000000
    int T;
    ll n,m,k,p;
    int is[maxnn];
    int ty=0;
    int book[maxnn][55];
    int dfn[maxnn],low[maxnn],vii,instack[maxnn];
    int las[maxn],en[maxn],le[maxn],tot,nex[maxn];
    int zlas[maxn],zen[maxn],zle[maxn],ztot,znex[maxn];
    int las1[maxn],en1[maxn],le1[maxn],tot1,nex1[maxn];
    ll dis[maxnn];
    ll dis1[maxnn];
    int mark[maxnn];
    int ttt[maxnn];
    int co[maxnn];
    int sec;
    int belong[maxnn];
    int mask[maxnn];
    stack<int > S;
    void tarjan(int u) {
        int v;
        mask[u]=1;
        dfn[u]=low[u]=++vii;
        instack[u]=1;
        S.push(u);
        for(int i=zlas[u]; i; i=znex[i]) {
            int y=zen[i];
            if(!dfn[y]) {
                tarjan(y);
                low[u]=min(low[u],low[y]);
            } else if(dfn[y]&&instack[y]) {
                low[u]=min(low[u],dfn[y]);
            }
        }
        if(dfn[u]==low[u]) {
            sec++;
            do {
                v=S.top();
                S.pop();
                belong[v]=sec;
                if(dis[v]+dis1[v]<=dis[n]+k)
                {
                    is[sec]=1;
                }
                ttt[sec]++;
                instack[v]=0;
            } while(v!=u);
        }
        if(ttt[sec]>=2&&is[sec])
        {
                ty=1;
        }
    }
    queue<int > Q;
    void spfa() {
        for(int i=1; i<=n; i++) {
            mark[i]=0;
            dis[i]=inf;
        }
        dis[1]=0;
        Q.push(1);
        while(Q.size()) {
            int v=Q.front();
            mark[v]=0;
            Q.pop();
            for(int i=las1[v]; i; i=nex1[i]) {
                int u=en1[i];
                if(dis[u]>dis[v]+le1[i]) {
                    dis[u]=dis[v]+le1[i];
                    if(!mark[u]) {
                        Q.push(u);
                    }
                }
            }
        }
    }
    void spfa1() {
        for(int i=1; i<=n; i++) {
            mark[i]=0;
            dis1[i]=inf;
        }
        dis1[n]=0;
        Q.push(n);
        while(Q.size()) {
            int v=Q.front();
            mark[v]=0;
            Q.pop();
            for(int i=las[v]; i; i=nex[i]) {
                int u=en[i];
                if(dis1[u]>dis1[v]+le[i]) {
                    dis1[u]=dis1[v]+le[i];
                    if(!mark[u]) {
                        Q.push(u);
                    }
                }
            }
        }
    }
    
    void zadd(int a,int b,int c) {
        zen[++ztot]=b;
        znex[ztot]=zlas[a];
        zlas[a]=ztot;
        zle[ztot]=c;
    }
    void add1(int a,int b,int c) {
        en1[++tot1]=b;
        nex1[tot1]=las1[a];
        las1[a]=tot1;
        le1[tot1]=c;
    }
    void add(int a,int b,int c) {
        en[++tot]=b;
        nex[tot]=las[a];
        las[a]=tot;
        le[tot]=c;
    }
    ll dfs(int v,ll k) {
        if(~f[v][k]) return f[v][k];
        if(v==1)
        {
            if(k==0)
            return 1;
            
        } 
        ll ans=0;
        for(int i=las[v]; i; i=nex[i]) {
            int u=en[i];
            if(k-(dis[u]+1LL*le[i]-dis[v])>=0)
             ans=(ans+dfs(u,1LL*k-(dis[u]+1LL*le[i]-dis[v])))%p;
            }
        f[v][k]=ans%p;
        return f[v][k];
    }
    void clear()
    {
        ty=0;
          memset(is,0,sizeof(is));
        while(S.size()) S.pop();
            memset(mark,0,sizeof(mark));
            memset(f,-1,sizeof(f));
            memset(book,0,sizeof(book));
            memset(las1,0,sizeof(las1));
            memset(zlas,0,sizeof(zlas));
            memset(las,0,sizeof(las));
            memset(en1,0,sizeof(en1));
            memset(zen,0,sizeof(zen));
            memset(en,0,sizeof(en));
            memset(nex1,0,sizeof(nex1));
            memset(nex,0,sizeof(nex));
            memset(znex,0,sizeof(znex));
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(le,0,sizeof(le));
            memset(le1,0,sizeof(le1));
            memset(instack,0,sizeof(instack));
            memset(mask,0,sizeof(mask));
            memset(belong,0,sizeof(belong));
            memset(co,0,sizeof(co));
            memset(ttt,0,sizeof(ttt));
            ztot=0;
    }
    int main() {
    	freopen("tes","r",stdin);
    	freopen("anss","w",stdout);
        cin>>T;
        while(T--) {
           clear();
            sec=0;
            tot1=0;
            vii=0;
            tot=0;
            int a,b,c;
            cin>>n>>m>>k>>p;
            
            for(int i=1; i<=m; i++) {
                cin>>a>>b>>c;
                add1(a,b,c);
                add(b,a,c);
                if(c==0)
                {
                    zadd(a,b,c);
                }
            }
         
            spfa();
            spfa1();
            ll ans=0; 
            for(int i=1; i<=n; i++)
             if(!mask[i]) tarjan(i); 
             
             if(ty)
             {
                 puts("-1");
                 continue;
             }
           for(int i=0;i<=k;i++)
            ans=(ans+dfs(n,i))%p;
                printf("%lld
    ",ans%p);
        }
    }
    
  • 相关阅读:
    centos7装NVIDIA显卡驱动
    前端MVC学习笔记(三)——AngularJS服务、路由、内置API、jQueryLite
    前端MVC学习笔记(二)——AngularJS验证、过滤器、指令
    前端MVC学习笔记(一)——MVC概要与angular概要、模板与数据绑定
    JavaScript学习笔记(四)——jQuery插件开发与发布
    JavaScript学习笔记(三)——this、原型、javascript面向对象
    Node.js学习笔记——Node.js开发Web后台服务
    JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象
    JavaScript学习笔记(一)——延迟对象、跨域、模板引擎、弹出层、AJAX示例
    【趣味分享】C#实现回味童年的24点算法游戏
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11708637.html
Copyright © 2020-2023  润新知