zoukankan      html  css  js  c++  java
  • [NOIP2017]逛公园(DP)

    先spfa一遍处理出d[]数组,(从n开始bfs一遍标记可以达到n的点)

    题意即,在走最短路的基础上,可以最多多走K长度的路径,

    考虑DP,每次剩余可走的长度会因决策而改变,所以考虑dp[i][j]为当前在i号节点,剩余可多走长度为j的方案数

    dp[u][j]可以从dp[v][e[i].w-(d[v]-d[u])]转移而来,(其中u->v,e[i].w-(d[v]-d[u])即为当前决策多走的路径))

    再考虑有0边的情况,如果构成环就会无限方案数,只要在记忆化的时候特判一下-1即可

    ps:对于一个dp[u][j]可能为0,初始化不能为0

    Code

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cstring>
    #define N 100010
    using namespace std;
    
    struct info{int to,nex,w;}e[N*2],re[N*2];
    int T,n,m,k,mo,tot,head[N],d[N],rtot,rhead[N],dp[N][56];
    bool ab[N];
    bool vis[N][56];
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    void Init(){
    	memset(vis,0,sizeof(vis));
    	memset(head,0,sizeof(head));
    	memset(rhead,0,sizeof(rhead));
    	memset(ab,0,sizeof(ab));
    	memset(dp,-1,sizeof(dp));
    	tot=rtot=0;
    }
    
    inline void Link(int u,int v,int w){
    	e[++tot].to=v,e[tot].w=w;e[tot].nex=head[u];head[u]=tot;
    }
    
    inline void rLink(int u,int v,int w){
    	re[++rtot].to=v,re[rtot].w=w;re[rtot].nex=rhead[u];rhead[u]=rtot;
    }
    
    namespace SPFA{
    	queue<int> q;
    	bool vis[N];
    	void spfa(){
    		for(;!q.empty();q.pop());
    		memset(vis,0,sizeof(vis));
    		memset(d,127,sizeof(d));
    		d[1]=0,q.push(1);
    		for(;!q.empty();){
    			int u=q.front();vis[u]=0,q.pop();
    			for(int i=head[u];i;i=e[i].nex){
    				int v=e[i].to;
    				if(d[v]>d[u]+e[i].w){
    					d[v]=d[u]+e[i].w;
    					if(!vis[v]) vis[v]=1,q.push(v);
    				}
    			}
    		}
    		memset(vis,0,sizeof(vis));
    	}
    	void afps(){
    		for(;!q.empty();q.pop());
    		q.push(n),ab[n]=1;
    		for(;!q.empty();){
    			int u=q.front();q.pop();
    			for(int i=rhead[u];i;i=re[i].nex){
    				int v=re[i].to;
    				if(ab[v]) continue;
    				ab[v]=1,q.push(v);
    			}
    		}
    	}
    	void work(){spfa(),afps();}
    }
    
    int DP(int u,int k){
    	if(k<0)return 0;
    	int &tmp=dp[u][k];
    	if(vis[u][k]) return -2;
    	if(tmp!=-1) return tmp;
    	vis[u][k]=1;
    	tmp=(u==n)?1:0;
    	for(int i=head[u];i;i=e[i].nex){
    		int v=e[i].to;
    		if(!ab[v]) continue;
    		int x=DP(v,k-(e[i].w-(d[v]-d[u])));
    		if(x==-2) return -2;
    		else (tmp+=x)%=mo;
    	}
    	vis[u][k]=0;
    	return tmp;
    }
    
    int main(){
    	for(T=read();T--;){
    		Init();
    		n=read(),m=read(),k=read(),mo=read();
    		for(;m--;){
    			int u=read(),v=read(),w=read();
    			Link(u,v,w),rLink(v,u,w);
    		}
    		SPFA::work();
    		int Ans=DP(1,k);
    		if(Ans==-2)puts("-1");
    		else printf("%d
    ",Ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    window server2019+vmware16+Ubuntu20部署网站记录
    CentOS7源码安装MySQL
    CentOS7源码安装Python、virtualenv虚拟环境安装、uwsgi安装配置
    CentOS7 源码安装Nginx及Nginx基本管理设置
    Ubuntu 64位桌面版 16.04.1 设置桥接模式和固定静态IP方法
    Windows 下日志保存至Linux rsyslog日志服务器
    python 接参数的一个小坑
    历旧服务器配置注意事项
    gitlab设置邮件通知
    Linux基础篇之目录与文件
  • 原文地址:https://www.cnblogs.com/void-f/p/9332684.html
Copyright © 2011-2022 走看看