codevs 1391 伊吹萃香
2016-11-03 09:36
211 查看
codevs 1391 伊吹萃香
题目描述 Description
在幻想乡,伊吹萃香是能够控制物体密度的鬼王。因为能够控制密度,所以萃香能够制造白洞和黑洞,并可以随时改变它们。某一天萃香闲着无聊,在妖怪之山上设置了一些白洞或黑洞,由于引力的影响,给妖怪们带来了很大的麻烦。于是他们决定找出一条消耗体力最少的路,来方便进出。已知妖怪之山上有N个路口(编号1..N),每个路口都被萃香设置了一定质量白洞或者黑洞。原本在各个路口之间有M条单向路,走过每一条路需要消耗一定量的体力以及1个单位的时间。由于白洞和黑洞的存在,走过每条路需要消耗的体力也就产生了变化,假设一条道路两端路口黑白洞的质量差为delta:
从有白洞的路口走向有黑洞的路口,消耗的体力值减少delta,若该条路径消耗的体力值变为负数的话,取为0。
从有黑洞的路口走向有白洞的路口,消耗的体力值增加delta。
如果路口两端均为白洞或黑洞,消耗的体力值无变化。
由于光是放置黑洞白洞不足以体现萃香的强大,所以她决定每过1个单位时间,就把所有路口的白洞改成黑洞,黑洞改成白洞。当然在走的过程中你可以选择在一个路口上停留1个单位的时间,如果当前路口为白洞,则不消耗体力,否则消耗s[i]的体力。现在请你计算从路口1走到路口N最小的体力消耗。保证一定存在道路从路口1到路口N。
输入描述 Input Description
第1行:2个正整数N, M
第2行:N个整数,第i个数为0表示第i个路口开始时为白洞,1表示黑洞
第3行:N个整数,第i个数表示第i个路口设置的白洞或黑洞的质量w[i]
第4行:N个整数,第i个数表示在第i个路口停留消耗的体力s[i]
第5..M+4行:每行3个整数,u, v, k,表示在没有影响的情况下,从路口u走到路口v需要消耗k的体力。
输出描述 Output Description
第1行:1个整数,表示消耗的最小体力
样例输入 Sample Input
4 5
1 0 1 0
10 10 100 10
5 20 15 10
1 2 30
2 3 40
1 3 20
1 4 200
3 4 200
样例输出 Sample Output
130
数据范围及提示 Data Size & Hint
对于30%的数据:1 <= N <= 100, 1 <= M <= 500
对于60%的数据:1 <= N <= 1,000, 1 <= M <= 5,000
对于100%的数据:1 <= N <= 5,000, 1 <= M <= 30,000
其中20%的数据为1 <= N <= 3000的链
1 <= u,v <= N, 1 <= k,w[i],s[i] <= 200
按照1 -> 3 -> 4的路线。
思路:
spfa+分层图,时间变化只需要改变奇偶,每次交替更新用奇数更新偶数,用偶数更新奇数。
题解:
注*:不知为何数组开3w在本地会RE,开到3000w才会过编译,而交上RE的程序却可以AC,若有相似情况请注意。
题目描述 Description
在幻想乡,伊吹萃香是能够控制物体密度的鬼王。因为能够控制密度,所以萃香能够制造白洞和黑洞,并可以随时改变它们。某一天萃香闲着无聊,在妖怪之山上设置了一些白洞或黑洞,由于引力的影响,给妖怪们带来了很大的麻烦。于是他们决定找出一条消耗体力最少的路,来方便进出。已知妖怪之山上有N个路口(编号1..N),每个路口都被萃香设置了一定质量白洞或者黑洞。原本在各个路口之间有M条单向路,走过每一条路需要消耗一定量的体力以及1个单位的时间。由于白洞和黑洞的存在,走过每条路需要消耗的体力也就产生了变化,假设一条道路两端路口黑白洞的质量差为delta:
从有白洞的路口走向有黑洞的路口,消耗的体力值减少delta,若该条路径消耗的体力值变为负数的话,取为0。
从有黑洞的路口走向有白洞的路口,消耗的体力值增加delta。
如果路口两端均为白洞或黑洞,消耗的体力值无变化。
由于光是放置黑洞白洞不足以体现萃香的强大,所以她决定每过1个单位时间,就把所有路口的白洞改成黑洞,黑洞改成白洞。当然在走的过程中你可以选择在一个路口上停留1个单位的时间,如果当前路口为白洞,则不消耗体力,否则消耗s[i]的体力。现在请你计算从路口1走到路口N最小的体力消耗。保证一定存在道路从路口1到路口N。
输入描述 Input Description
第1行:2个正整数N, M
第2行:N个整数,第i个数为0表示第i个路口开始时为白洞,1表示黑洞
第3行:N个整数,第i个数表示第i个路口设置的白洞或黑洞的质量w[i]
第4行:N个整数,第i个数表示在第i个路口停留消耗的体力s[i]
第5..M+4行:每行3个整数,u, v, k,表示在没有影响的情况下,从路口u走到路口v需要消耗k的体力。
输出描述 Output Description
第1行:1个整数,表示消耗的最小体力
样例输入 Sample Input
4 5
1 0 1 0
10 10 100 10
5 20 15 10
1 2 30
2 3 40
1 3 20
1 4 200
3 4 200
样例输出 Sample Output
130
数据范围及提示 Data Size & Hint
对于30%的数据:1 <= N <= 100, 1 <= M <= 500
对于60%的数据:1 <= N <= 1,000, 1 <= M <= 5,000
对于100%的数据:1 <= N <= 5,000, 1 <= M <= 30,000
其中20%的数据为1 <= N <= 3000的链
1 <= u,v <= N, 1 <= k,w[i],s[i] <= 200
按照1 -> 3 -> 4的路线。
思路:
spfa+分层图,时间变化只需要改变奇偶,每次交替更新用奇数更新偶数,用偶数更新奇数。
题解:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> using namespace std; const int maxn=30000+10; struct cc{ int from,to,cost; }es[maxn]; bool color[maxn],vis[maxn][2]; int w[maxn],s[maxn]; int dis[maxn][2]; int first[maxn],next[maxn]; int tot=0; void build(int ff,int tt,int pp) { es[++tot]=(cc){ff,tt,pp}; next[tot]=first[ff]; first[ff]=tot; } struct edge{ int u; bool pd; }; int dist(int v,int u,bool pd) { int f=color[v]^pd; int t=color[u]^pd; int weigh=abs(w[v]-w[u]); if(f==t) { return 0; } if(f==1&&t==0) { return weigh; } if(f==0&&t==1) { return -weigh; } } deque<edge>q; void spfa(int start) { dis[start][0]=0; vis[start][0]=1; edge begin; begin.u=start,begin.pd=0; q.push_back(begin); while(!q.empty()) { edge x=q.front(); q.pop_front(); vis[x.u][x.pd]=0; int v=x.u; for(int i=first[v];i;i=next[i]) { int u=es[i].to; if(dis[u][x.pd^1]>dis[v][x.pd]+max(es[i].cost+dist(v,u,x.pd),0)) { dis[u][x.pd^1]=dis[v][x.pd]+max(es[i].cost+dist(v,u,x.pd),0); if(!vis[u][x.pd^1]) { if(dis[u][x.pd^1]<=dis[q.front().u][q.front().pd]) { q.push_front((edge){u,x.pd^1}); } else { q.push_back((edge){u,x.pd^1}); } vis[u][x.pd^1]=1; } } } if(dis[v][x.pd^1]>dis[v][x.pd]+s[v]*(color[v]^x.pd)) { dis[v][x.pd^1]=dis[v][x.pd]+s[v]*(color[v]^x.pd); if(!vis[v][x.pd^1]) { if(dis[v][x.pd^1]<=dis[q.front().u][q.front().pd]) { q.push_front((edge){v,x.pd^1}); } else { q.push_back((edge){v,x.pd^1}); } vis[v][x.pd^1]=1; } } } } int main() { memset(dis,63,sizeof(dis)); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&color[i]); } for(int i=1;i<=n;i++) { scanf("%d",&w[i]); } for(int i=1;i<=n;i++) { scanf("%d",&s[i]); } for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); build(x,y,z); } spfa(1); printf("%d",min(dis [0],dis [1])); return 0; }
注*:不知为何数组开3w在本地会RE,开到3000w才会过编译,而交上RE的程序却可以AC,若有相似情况请注意。
相关文章推荐
- [Codevs P1391]伊吹萃香
- [CODEVS P1391]伊吹萃香
- XYLX 10.26 虫洞/Codevs P1391 伊吹萃香
- codevs1391 伊吹萃香
- codevs 1391 伊吹萃香
- Code vs 1391 伊吹萃香(虫洞)
- codevs 1922 骑士共存问题 网络流
- codevs 抄书问题系列
- 单词接龙codevs1018(noip2000)
- 虚拟机使用ubuntu运行VS code出现界面黑屏时的解决办法
- 洛谷P1395 会议(CODEVS.3029.设置位置)(求树的重心)
- CODEVS 1073家族
- code vs 1315 摆花 (dp)
- VS Code 折腾记 - (8) 新一波实用插件推荐(前端)|NG2+|TS2|Vue|React|Node|版本控制|主题
- 【基础练习】【背包DP】codevs1068 乌龟棋题解
- Hankson 的趣味题(codevs 1172)
- Codevs 5208 求乘方取模
- wamp+php+vscode
- intall vs code in elementary os
- codevs1002 搭桥