首页 > 其他 > 详细

[NOIP2017]逛公园

时间:2018-09-07 18:54:59      阅读:157      评论:0      收藏:0      [点我收藏+]

很难的一道$dp$,考场上我只得了$10$分。。其实如果做过这道题对于状态的设计就会有所感觉

设$dp[i][j]$表示到$i$点还剩$j$的距离可以去用,也就是说如果$j$等于0时,就只能严格按最短路走到$n$,否则可以沿着其他路走,但不能让$j$走成0

首先跑一遍最短路,求出一号店到其他点的距离,然后建反图跑。这样就有$70$分。至于零环的处理我们可以这样想,假如我们花费$k$的费用到达$i$号点,再从该店往外走,当我们到达另一个点且仍花费$k$时,如果该点到$i$号点有边且费用为0,那么这中间就形成了一个零环

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #define M 200010
 6 using namespace std;
 7 int read()
 8 {
 9     char ch=getchar();int x=0;
10     while(ch>9||ch<0) ch=getchar();
11     while(ch<=9&&ch>=0) x=x*10+ch-0,ch=getchar();
12     return x;
13 }
14 int n,m,k,mod,num;
15 int head[M],dis[M],lft[M],dp[M][60],a[M],b[M],c[M];
16 bool flag,vis[M],in[M];
17 struct point{int to,next,dis;}e[M<<1];
18 void add(int u,int v,int dis) {e[++num].next=head[u];e[num].to=v;e[num].dis=dis;head[u]=num;}
19 void SPFA()
20 {
21     queue<int>q;q.push(1);
22     memset(dis,0x3f,sizeof(dis));
23     vis[1]=true; dis[1]=0;
24     while(!q.empty())
25     {
26         int x=q.front();q.pop();
27         for(int i=head[x];i;i=e[i].next)
28         {
29             int to=e[i].to;
30             if(dis[to]>dis[x]+e[i].dis)
31             {
32                 dis[to]=dis[x]+e[i].dis;
33                 if(!vis[to])
34                 {
35                     q.push(to);
36                     vis[to]=true;
37                 }
38             }
39         }
40         vis[x]=false;
41     }
42 }
43 int DFS(int x,int left)
44 {
45     if(~dp[x][left]) return dp[x][left];
46     dp[x][left]=(x==1);
47     for(int i=head[x];i;i=e[i].next)
48     {
49         int to=e[i].to;
50         int k=left-(dis[to]+e[i].dis-dis[x]);
51         if(k<0) continue;
52         if(in[to]&&lft[to]==k) flag=true;
53         else in[to]=true,lft[to]=k;
54         dp[x][left]=(dp[x][left]+DFS(to,k))%mod;
55         in[to]=false;lft[to]=0;
56     }
57     return dp[x][left];
58 }
59 void work()
60 {
61     memset(head,0,sizeof(head)); num=0;
62     n=read();m=read();k=read();mod=read();
63     for(int i=1;i<=m;i++)
64     {
65         a[i]=read(),b[i]=read(),c[i]=read();
66         add(a[i],b[i],c[i]);
67     }
68     SPFA();
69     memset(head,0,sizeof(head));num=0;
70     for(int i=1;i<=m;i++) add(b[i],a[i],c[i]);
71     memset(dp,-1,sizeof(dp)); memset(lft,0,sizeof(lft));
72     memset(in,0,sizeof(in)); flag=false;
73     DFS(n,k);
74     printf("%d\n",flag?-1:DFS(n,k));
75 }
76 int main()
77 {
78     int T=read();
79     while(T--) work();
80     return 0;
81 }

 

[NOIP2017]逛公园

原文:https://www.cnblogs.com/Slrslr/p/9606550.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!