标签:eof 相同 存在 color std name 执行 text tps
题目描述
阿龙要从1号节点到n号节点,每个节点对于一种商品有买入价和卖出价,同一节点买入价和卖出价相同,求在只执行一次买卖最多可以转多少钱。(可从夫经过节点)。
思路
首先我们考虑对于同一节点的买卖状态,我们只有3种:买,卖,不买不卖。那么显然,我们只需要对于每一个状态建一层图,在不买不卖和买之间连边,在买和卖之间连边,由于只会进行一次贸易,所以实际两种的状态我们分为三种(实际只有有水晶球和无水晶球),卖完之后无法再回到不买不卖这一层,这样就保证了只进行一次贸易。在这张图上跑一遍最短路,由于存在负权,我们只能跑spfa。
代码
#include <bits/stdc++.h> using namespace std; const int N=1e5+10,M=1e6+20; int nxt[M],to[M],w[M],head[N],tot,n,m; int v[N],dis[N<<2]; bool exist[N<<2]; void add_edge(int x,int y,int v) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; w[tot]=v; } void build() { for(int i=1;i<=n;i++) { add_edge(i,i+n,v[i]); add_edge(i+n,i+n*2,-v[i]); } } void spfa() { memset(dis,0x3f,sizeof(dis)); queue<int>q; dis[1]=0;q.push(1);exist[1]=1; while(!q.empty()) { int u=q.front();q.pop(); exist[u]=0; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(dis[v]>dis[u]+w[i]) { dis[v]=dis[u]+w[i]; if(!exist[v]) { q.push(v); exist[v]=1; } } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(z==1)add_edge(x,y,0),add_edge(x+n,y+n,0),add_edge(x+n*2,y+n*2,0); else { add_edge(x,y,0);add_edge(x+n,y+n,0);add_edge(x+n*2,y+n*2,0); add_edge(y,x,0);add_edge(y+n,x+n,0);add_edge(y+n*2,x+n*2,0) ; } } build(); spfa(); int ans=0x3f3f3f3f; for(int i=0;i<3;i++) ans=min(ans,dis[i*n+n]); printf("%d",-ans); return 0; }
标签:eof 相同 存在 color std name 执行 text tps
原文地址:https://www.cnblogs.com/fangbozhen/p/11683232.html