D 斩杀线计算大师 同余最短路

链接:https://ac.nowcoder.com/acm/contest/4853/D

思路:直接按同余最短路的方式建最短路找出最小剩余系;

   然后找出满足条件的余数进行操作即可

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define INF 0x3f3f3f3f
 4 #define N 1000010
 5 using namespace std;
 6 ll first[N],nxt[N],go[N],cost[N],tot;
 7 ll dist[N],vis[N],h,x,y,z,ans;
 8 void add_edge(ll u,ll v,ll w){
 9     nxt[++tot]=first[u];
10     first[u]=tot;
11     go[tot]=v;
12     cost[tot]=w;
13 }
14 void spfa()
15 {
16     queue<ll>q;
17     memset(dist,INF,sizeof(dist));
18     memset(vis,0,sizeof(vis));
19     dist[0]=0;vis[0]=1;
20     q.push(0);
21     while(!q.empty()){
22         ll u=q.front();q.pop();
23         vis[u]=0;
24         for(ll e=first[u];e;e=nxt[e]){
25             ll v=go[e],w=cost[e];
26             if(dist[v]>dist[u]+w){
27                 dist[v]=dist[u]+w;
28                 if(!vis[v]){
29                     q.push(v);
30                     vis[v]=1;
31                 }
32             }
33         }
34     }
35 }
36 int main()
37 {
38     scanf("%lld%lld%lld%lld",&x,&y,&z,&h);
39     if(x==1||y==1||z==1){printf("%d",h);return 0;}//可以直接到任何楼层
40     for(int i=0;i<=x-1;i++){
41         add_edge(i,(i+y)%x,y);
42         add_edge(i,(i+z)%x,z);
43     }
44     spfa();
45     for(int i=0;i<=x-1;i++){
46         if(dist[i]<=h){
47             if((h-dist[i])%x==0){
48                // printf("dist:%lld\n",dist[i]);
49                 for(ll k=dist[i]/y;k>=0;k--){
50                     ll tmp=dist[i]-k*y;
51                     if(tmp%z==0){
52                         printf("%lld %lld %lld\n",(h-dist[i])/x,k,tmp/z);
53                         return 0;
54                     }
55                 }
56             }
57         }
58     }
59     return 0;
60 }
View Code

 

posted @ 2020-05-19 19:17  古比  阅读(160)  评论(0编辑  收藏  举报