feat(P3953): 实现基于DFS的路径计数算法替代BFS

用DFS加记忆化搜索替换原有的BFS实现,解决大规模数据下的性能问题
新增距离数组d和动态规划数组dp来优化计算
添加反向图re支持逆向搜索
处理路径计数中的环检测和边界条件
This commit is contained in:
Zengtudor 2025-11-05 16:17:11 +08:00
parent a788926d44
commit 5cb2778d2c

View File

@ -8,8 +8,9 @@
using ll = int64_t; using ll = int64_t;
#define sl static inline #define sl static inline
// #define printf // #define printf
const ll maxm=2e5+5; const ll maxm=2e5+5,inf=1e9+7;
ll n,m,k,p,nt; ll n,m,k,p,nt,d[maxm],dp[maxm][57];
bool isn,vis[maxm][57];
struct E{ struct E{
ll v,w; ll v,w;
}; };
@ -19,36 +20,78 @@ struct P{
return step>o.step; return step>o.step;
} }
}; };
std::vector<std::vector<E>> edg; std::vector<std::vector<E>> edg,re;
std::bitset<maxm> vis;
std::deque<P>dq; std::deque<P>dq;
sl ll dj(){ sl ll dj(){
vis.reset(); for(ll i=1;i<=n;i++){
d[i]=inf;
}
std::priority_queue<P> pq; std::priority_queue<P> pq;
pq.emplace(1,0); pq.emplace(1,0);
while(pq.size()){ while(pq.size()){
auto[now,step]=pq.top(); auto[now,step]=pq.top();
// printf("dj now=%lld, step=%lld\n",now,step);
pq.pop(); pq.pop();
if(now==n)return step; if(step>=d[now])continue;
if(vis[now])continue; d[now]=step;
vis[now]=true;
for(auto[v,w]:edg[now]){ for(auto[v,w]:edg[now]){
pq.emplace(v,step+w); pq.emplace(v,step+w);
} }
} }
return -1;
printf("d[]:");
for(ll i=1;i<=n;i++){
printf("%lld ",d[i]);
}
printf("\n");
return d[n]==inf?-1:d[n];
}
sl ll dfs(ll u,ll k){
if(k<0||k>::k)return 0;
if(vis[u][k]){
isn=true;
return 0;
}
if(u==1)return k==0?1:0;
vis[u][k]=true;
if(dp[u][k]!=-1){
return dp[u][k];
}
ll nans=0;
for(auto[v,w]:re[u]){
ll nk=d[u]+k-d[v]-w;
if(nk<0||nk>k)continue;
nans=(nans+dfs(v, nk))%p;
if(isn){
return 0;
}
}
vis[u][k]=false;
return dp[u][k]=nans;
} }
sl void solve(){ sl void solve(){
printf("NT = %lld\n",++nt); printf("NT = %lld\n",++nt);
std::cin>>n>>m>>k>>p; std::cin>>n>>m>>k>>p;
isn=false;
edg.clear(); edg.clear();
edg.resize(n+1); edg.resize(n+1);
re.clear();
re.resize(n+1);
for(ll i=1;i<=n;i++){
for(ll j=1;j<=50;j++){
dp[i][j]=-1;
vis[i][j]=false;
}
}
dp[1][0]=1;
for(ll i=1;i<=m;i++){ for(ll i=1;i<=m;i++){
ll u,v,w; ll u,v,w;
std::cin>>u>>v>>w; std::cin>>u>>v>>w;
edg[u].emplace_back(v,w); edg[u].emplace_back(v,w);
re[v].emplace_back(u,w);
} }
const ll d = dj(); const ll d = dj();
printf("found d=%lld\n",d); printf("found d=%lld\n",d);
@ -58,27 +101,14 @@ sl void solve(){
} }
const ll ms=d+k; const ll ms=d+k;
ll ans=0; ll ans=0;
dq.clear(); for(ll i=0;i<=k;i++){
dq.emplace_back(1,0); ans=(ans+dfs(n,i))%p;
ll tick=0; if(isn){
while(dq.size()){ std::cout<<"-1\n";
tick++;
if(tick>1e6){
std::cout<<-1<<"\n";
return; return;
} }
auto[now,step]=dq.front();
dq.pop_front();
if(now==n){
ans++;
}
for(auto[v,w]:edg[now]){
const ll ns=w+step;
if(ns>ms)continue;
dq.emplace_back(v,ns);
}
} }
std::cout<<ans%p<<"\n"; std::cout<<ans<<"\n";
} }
int main(){ int main(){