luogu3563 逛公园

两遍 spfa 然后建立分层图拓扑排序 dp 一下。
写得很差劲。效率很低。
时间复杂度 (mathrm{O}(Tnk))
参见这里秒懂。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int T, n, m, k, p, cnt[2], hea[2][100005], dis[2][100005], uu, vv, ww, he[5100005], cn, dp[5100005];
int ind[5100005], f[100005][55];
bool vis[5100005];
queue<int> d;
struct Edge{
	int too, nxt, val;
}edge[2][200005], edg[10200005];
void rn(int &x){
	char ch=getchar();
	x = 0;
	while(ch<'0' || ch>'9')	ch = getchar();
	while(ch>='0' && ch<='9'){
		x = x * 10 + ch - '0';
		ch = getchar();
	}
}
void add_edge(int rr, int fro, int too, int val){
	edge[rr][++cnt[rr]].nxt = hea[rr][fro];
	edge[rr][cnt[rr]].too = too;
	edge[rr][cnt[rr]].val = val;
	hea[rr][fro] = cnt[rr];
}
void add_edg(int fro, int too){
	edg[++cn].nxt = he[fro];
	edg[cn].too = too;
	he[fro] = cn;
}
void init(){
	rn(n); rn(m); rn(k); rn(p);
	memset(he, 0, sizeof(he));
	memset(dp, 0, sizeof(dp));
	memset(hea, 0, sizeof(hea));
	memset(vis, 0, sizeof(vis));
	memset(ind, 0, sizeof(ind));
	memset(dis, 0x3f, sizeof(dis));
	dis[0][1] = dis[1][n] = cnt[0] = cnt[1] = cn = 0;
	dp[1] = 1;
	for(int i=1; i<=m; i++){
		rn(uu); rn(vv); rn(ww);
		add_edge(0, uu, vv, ww);
		add_edge(1, vv, uu, ww);
	}
	int qwq=0;
	for(int i=1; i<=n; i++)
		for(int j=0; j<=k; j++)
			f[i][j] = ++qwq;
}
void spfa(int rr){
	d.push(rr?n:1);
	vis[rr?n:1] = true;
	while(!d.empty()){
		int x=d.front();
		d.pop();
		vis[x] = false;
		for(int i=hea[rr][x]; i; i=edge[rr][i].nxt){
			int t=edge[rr][i].too;
			if(dis[rr][t]>dis[rr][x]+edge[rr][i].val){
				dis[rr][t] = dis[rr][x] + edge[rr][i].val;
				if(!vis[t]){
					vis[t] = true;
					d.push(t);
				}
			}
		}
	}
}
void build(){
	for(int i=1; i<=n; i++)
		for(int j=0; j<=k; j++)
			if(dis[0][i]+dis[1][i]+j<=dis[0][n]+k)
				vis[f[i][j]] = true;
	for(int i=1; i<=n; i++)
		for(int j=0; j<=k; j++)
			if(vis[f[i][j]])
				for(int l=hea[0][i]; l; l=edge[0][l].nxt){
					int t=edge[0][l].too, v=j+dis[0][i]+edge[0][l].val-dis[0][t];
					if(v<=k && f[t][v]){
						add_edg(f[i][j], f[t][v]);
						ind[f[t][v]]++;
					}
				}
}
void topsort(){
	for(int i=1; i<=n; i++)
		for(int j=0; j<=k; j++)
			if(vis[f[i][j]] && !ind[f[i][j]])
				d.push(f[i][j]);
	while(!d.empty()){
		int x=d.front();
		d.pop();
		for(int i=he[x]; i; i=edg[i].nxt){
			int t=edg[i].too;
			ind[t]--;
			if(ind[t]==0)	d.push(t);
			dp[t] = dp[t]+dp[x]>=p?dp[t]+dp[x]-p:dp[t]+dp[x];
		}
	}
}
int chk(){
	for(int i=1; i<=f[n][k]; i++)
		if(ind[i]!=0)
			return -1;
	int re=0;
	for(int i=0; i<=k; i++)
		re = re+dp[f[n][i]]>=p?re+dp[f[n][i]]-p:re+dp[f[n][i]];
	return re;
}
int main(){
	cin>>T;
	while(T--){
		init();
		spfa(0);
		spfa(1);
		build();
		topsort(); 
		printf("%d
", chk());
	}
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/8449742.html