[NOIP2017]逛公园

建一个反图跑个最短路,然后记忆化搜索一下。
(很迷的是堆优化dij就wa了,线段树优化的和spfa就A了。)(求dalao看看我的堆优化dij是不是打错了,但是过了80分)。
spfa的AC代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cctype>
#include <cstring>
using namespace std;
const int N=100005;
int T,n,m,K,p,ecnt,head[N],dis[N],fhead[N];
bool vis[N];
long long f[N][51];
bool inq[N][51];
struct Edge{int to,nxt,val;}e[N<<2];
void add(int bg,int ed,int val){e[++ecnt].nxt=head[bg];e[ecnt].to=ed;e[ecnt].val=val;head[bg]=ecnt;}
void add2(int bg,int ed,int val){e[++ecnt].nxt=fhead[bg];e[ecnt].to=ed;e[ecnt].val=val;fhead[bg]=ecnt;}
int rd() {
  int x=0,f=1;char ch=getchar();
  while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
  while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
  return x*f;
}
struct Node{bool operator ()(int x,int y) {return dis[x]>dis[y];}};
void dij(){
  priority_queue<int,vector<int>,Node>q;
  memset(dis,0x3f,sizeof dis);
  memset(vis,0,sizeof vis);
  q.push(n);
  dis[n]=0;
  while(!q.empty()) {
    int u=q.top();q.pop();
    if(vis[u]) continue;
    vis[u]=1;
    for(int i=fhead[u];i;i=e[i].nxt) {
      int v=e[i].to;
      dis[v]=min(dis[v],dis[u]+e[i].val);
      q.push(v);
    }
  }
}
long long dp(int x,int k) {
  if(inq[x][k]) return -1;
  if(f[x][k]) return f[x][k];
  inq[x][k]=1;if(x==n) f[x][k]=1;else f[x][k]=0;
  for(int i=head[x];i;i=e[i].nxt) {
    int v=e[i].to;
    int tmp=dis[v]-dis[x]+e[i].val;
    if(tmp<=k) {
      int tp=dp(v,k-tmp);
      if(tp==-1) return f[x][k]=-1;
      f[x][k]=(f[x][k]+tp)%p;
    }
  }
  inq[x][k]=0;
  return f[x][k];
}
void spfa() {
  memset(dis,0x3f,sizeof dis);
  queue<int>q;
  q.push(n);
  vis[n]=1;dis[n]=0;
  while(!q.empty()) {
    int u=q.front();vis[u]=0;q.pop();
    for(int i=fhead[u];i;i=e[i].nxt) {
      int v=e[i].to;
      if(dis[u]+e[i].val<dis[v]) {
        dis[v]=dis[u]+e[i].val;
        if(!vis[v]) q.push(v),vis[v]=1;
      }
    }
  }
}
int main() {
  T=rd();
  while (T--) {
    memset(f,0,sizeof f);memset(inq,0,sizeof inq);memset(head,0,sizeof head);memset(fhead,0,sizeof fhead);ecnt=0;
    n=rd();m=rd();K=rd();p=rd();
    for(int i=1,a,b,c;i<=m;i++)
       a=rd(),b=rd(),c=rd(),add(a,b,c),add2(b,a,c);
    spfa();
    long long ans=dp(1,K);
    printf("%lld
",ans);
  }
}

堆优化的:

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cctype>
#include <cstring>
using namespace std;
const int N=100005;
int T,n,m,K,p,ecnt,head[N],dis[N],fhead[N];
bool vis[N];
long long f[N][51];
bool inq[N][51];
struct Edge{int to,nxt,val;}e[N<<2];
void add(int bg,int ed,int val){e[++ecnt].nxt=head[bg];e[ecnt].to=ed;e[ecnt].val=val;head[bg]=ecnt;}
void add2(int bg,int ed,int val){e[++ecnt].nxt=fhead[bg];e[ecnt].to=ed;e[ecnt].val=val;fhead[bg]=ecnt;}
int rd() {
  int x=0,f=1;char ch=getchar();
  while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
  while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
  return x*f;
}
struct Node{bool operator ()(int x,int y) {return dis[x]>dis[y];}};
void dij(){
  priority_queue<int,vector<int>,Node>q;
  memset(dis,0x3f,sizeof dis);
  memset(vis,0,sizeof vis);
  q.push(n);
  dis[n]=0;
  while(!q.empty()) {
    int u=q.top();q.pop();
    if(vis[u]) continue;
    vis[u]=1;
    for(int i=fhead[u];i;i=e[i].nxt) {
      int v=e[i].to;
      if(dis[u]+e[i].val>dis[v]) continue;
        dis[v]=min(dis[v],dis[u]+e[i].val);
      q.push(v);
    }
  }
}
long long dp(int x,int k) {
  if(inq[x][k]) return -1;
  if(f[x][k]) return f[x][k];
  inq[x][k]=1;if(x==n) f[x][k]=1;else f[x][k]=0;
  for(int i=head[x];i;i=e[i].nxt) {
    int v=e[i].to;
    int tmp=dis[v]-dis[x]+e[i].val;
    if(tmp<=k) {
      int tp=dp(v,k-tmp);
      if(tp==-1) return f[x][k]=-1;
      f[x][k]=(f[x][k]+tp)%p;
    }
  }
  inq[x][k]=0;
  return f[x][k];
}
int main() {
  T=rd();
  while (T--) {
    memset(f,0,sizeof f);memset(inq,0,sizeof inq);memset(head,0,sizeof head);memset(fhead,0,sizeof fhead);ecnt=0;
    n=rd();m=rd();K=rd();p=rd();
    for(int i=1,a,b,c;i<=m;i++)
       a=rd(),b=rd(),c=rd(),add(a,b,c),add2(b,a,c);
    dij();
    long long ans=dp(1,K);
    printf("%lld
",ans);
  }
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9359218.html