萌新求助,关于 dp 的顺序
查看原帖
萌新求助,关于 dp 的顺序
120074
BFqwqYoshino楼主2020/10/30 20:56

RT,这个题在 dp 的时候顺序应该怎么样才是对了,我直接用 tarjan 的 dfn 不行,然后用拓扑排序的 dfn 还是不行。。。

思路是 tarjan 判环,然后 dp 部分跟各种题解的基本一样。

#include<bits/stdc++.h> 
#define int long long
#define inf 0x3f3f3f3f
using namespace std;
int read(){
	bool f=1;
	int x=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=0;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<3)+(x<<1)-48+c;
		c=getchar();
	}
	return f?x:x*-1;
}
char cr[200];int tt;
inline void print(register int x,register char k='\n') {
    if(!x) putchar('0');
    if(x < 0) putchar('-'),x=-x;
    while(x) cr[++tt]=x%10+'0',x/=10;
    while(tt) putchar(cr[tt--]);
    putchar(k);
}
const int maxn=123333;
struct node{
	int to,val;
	friend bool operator <(node a,node b){
		return a.val>b.val;
	}
}tmp;
vector<node>e[maxn][2],e0[maxn];
int T,n,m,k,lim,p,ans,tot,top;
int in[maxn],id[maxn],dfn[maxn],st[maxn],lg[maxn];
int f[maxn][52],dis[maxn][2],low[maxn],sd[maxn];
bool vis[maxn][3],tag[maxn],flag;
void tarjan(int x){
    low[x]=dfn[x]=++tot;lg[x]++;
    st[++top]=x;vis[x][2]=1;
    for(node t:e0[x]){
        int v=t.to;
        if (!dfn[v]){
        	tarjan(v);
        	low[x]=min(low[x],low[v]);
    	}
        else if (vis[v]){
            low[x]=min(low[x],dfn[v]);
        }
    }
    if(dfn[x]==low[x]){
        int y;
        while(y=st[top--]){
            sd[y]=x;
            vis[y][2]=0;
            if(x==y) break;
            lg[x]+=lg[y];
        }
    }
}
void dij(int s,int o){
	priority_queue<node> q;
	dis[s][o]=0;
	tmp.to=s;tmp.val=0;
	q.push(tmp);
	while(!q.empty()){
		tmp=q.top();q.pop();
		int u=tmp.to;
		if(vis[u][o]) continue;
		vis[u][o]=1;
		for(node t:e[u][o]){
			int v=t.to;
			int w=t.val;
			if(dis[v][o]<=dis[u][o]+w) continue;
			dis[v][o]=dis[u][o]+w;
			tmp.to=v;tmp.val=dis[v][o];
			q.push(tmp);
		}
	}
}
void init(){
	flag=ans=tot=0;
	memset(f,0,sizeof(f));
	memset(lg,0,sizeof(lg));
	memset(sd,0,sizeof(sd));
	memset(id,0,sizeof(id));
	memset(tag,0,sizeof(tag));
	memset(vis,0,sizeof(vis));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(dis,0x3f,sizeof(dis));
	for(int i=1;i<=n;i++){
		e[i][0].clear();
		e[i][1].clear();
		e0[i].clear();
	}
}
bool cmp(int x,int y){
    if(dis[x][0]==dis[y][0])return dfn[x]<dfn[y];
    return dis[x][0]<dis[y][0];
}
void topo(){
	queue<int> q;
	for(int i=1;i<=n;i++){
		if(in[i]==0&&tag[i]){
			q.push(i);
		}
	}
	while(!q.empty()){
		int u=q.front();q.pop();
		dfn[u]=++tot;
		for(node t:e0[u]){
			int v=t.to;
			in[v]--;
			if(!in[v]){
				q.push(v);
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(!in[i]) continue;
		dfn[i]=++tot;
	}
}
signed main(){
	T=read();
	while(T--){
		init();
		n=read();m=read();k=read();p=read();
		priority_queue<node> q;
		for(int i=1;i<=m;i++){
			int u=read(),v=read(),w=read();
			tmp.to=v;tmp.val=w;e[u][0].push_back(tmp);
			tmp.to=u;e[v][1].push_back(tmp);
			if(w==0){
				tmp.to=v;e0[u].push_back(tmp);
				tag[u]=1;
				in[v]++;
			}
		}
		dij(1,0);dij(n,1);
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++){
			if(tag[i]&&!dfn[i]) tarjan(i);
		}
		lim=dis[n][0]+k;
		for(int i=1;i<=n;i++){
			if(tag[i]&&lg[sd[i]]>1&&dis[i][0]+dis[i][1]<=lim){
				flag=1;
			}
		}
		if(flag){
			print(-1);
			continue;
		}
		for(int i=1;i<=n;++i){
			id[i]=i;
		}
		tot=0;
		memset(dfn,0,sizeof(dfn));
		topo();
        sort(id+1,id+n+1,cmp);
        f[1][0]=1%p;
        for(int j=0;j<=k;j++){
            for(int t=1;t<=n;t++){
                int u=id[t];
                if(!f[u][j]){
                	continue;	
				}
                for(node d:e[u][0]){
                    int v=d.to;
					int w=dis[u][0]+j+d.val-dis[v][0];
                    if(w<=k){
                    	f[v][w]=(f[v][w]+f[u][j])%p;
					}
                }
            }
            ans=(ans+f[n][j])%p;
        }
        print(ans);
	}
	return 0;
}

调的我好累/kk

2020/10/30 20:56
加载中...