NOIP2017D1T3
考场上未曾光顾的一道题...
结果回来20min想出方程1hA掉了
我是真的蒻,Orz机房里其他的各位dalao
图上dp
两遍spfa(我写的dijkstra)判断一个点对答案的贡献
然后随便dp一下
零环在dp的时候单独处理一下,如果访问过一个点又访问回来了且目前超过的长度没变就是零环
然后就轻松加愉快咯
110行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; const int inf=2147483233; const int maxn=400010; #define pa pair<int,int> int n,m,k,T,P; int first[maxn],next[maxn],to[maxn],val[maxn],cnt; int First[maxn],Next[maxn],To[maxn],Val[maxn],Cnt; int u,v,w; inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();} while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();} return x*f; } inline void add(int u,int v,int w){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;val[cnt]=w;} inline void Add(int u,int v,int w){To[++Cnt]=v;Next[Cnt]=First[u];First[u]=Cnt;Val[Cnt]=w;} int dis[maxn],Dis[maxn]; int dp[maxn][60]; int used[maxn][60]; int ans; void dj() { priority_queue<pa,vector<pa>,greater<pa> > heap; dis[1]=0; heap.push(make_pair(0,1)); while(!heap.empty()) { int now=heap.top().second,no=heap.top().first;heap.pop(); if(dis[now]<no)continue; for(int i=first[now];i;i=next[i]) if(dis[to[i]]==-1 || dis[to[i]]>dis[now]+val[i]) { dis[to[i]]=dis[now]+val[i]; heap.push(make_pair(dis[to[i]],to[i])); } } } void DJ() { priority_queue<pa,vector<pa>,greater<pa> > heap; Dis[n]=0; heap.push(make_pair(0,n)); while(!heap.empty()) { int now=heap.top().second,no=heap.top().first;heap.pop(); if(Dis[now]<no)continue; for(int i=First[now];i;i=Next[i]) if(Dis[To[i]]==-1 || Dis[To[i]]>Dis[now]+Val[i]) { Dis[To[i]]=Dis[now]+Val[i]; heap.push(make_pair(Dis[To[i]],To[i])); } } } int solve(int u,int sum) { if(used[u][sum])return 1; if(~dp[u][sum])return 0; used[u][sum]=1; if(u==n)dp[u][sum]=1; else dp[u][sum]=0; int cur; for(int i=first[u];i;i=next[i]) { cur=dis[u]-dis[to[i]]+val[i]+sum; if(cur<=k && dis[u]+sum+val[i]+Dis[to[i]]-ans<=k) { if(solve(to[i],cur))return 1; dp[u][sum]+=dp[to[i]][cur]; if(dp[u][sum]>=P)dp[u][sum]-=P; } } used[u][sum]=0; return 0; } int main() { T=read(); while(T--) { n=read(),m=read(),k=read(),P=read();cnt=0,Cnt=0,ans=0; memset(first,0,sizeof(first));memset(to,0,sizeof(to)); memset(next,0,sizeof(next));memset(val,0,sizeof(val)); memset(First,0,sizeof(First));memset(To,0,sizeof(To)); memset(Next,0,sizeof(Next));memset(Val,0,sizeof(Val)); memset(dp,0xff,sizeof(dp));memset(used,0,sizeof(used)); memset(Dis,0xff,sizeof(Dis));memset(dis,0xff,sizeof(dis)); for(int i=1;i<=m;i++) { u=read(),v=read(),w=read(); add(u,v,w); Add(v,u,w); } dj(); DJ(); ans=Dis[1]; if(solve(1,0))puts("-1"); else printf("%d\n",dp[1][0]); } return 0; }