[最短路]JZOJ 3241 Money
分析
其实根本不需要最短路……货币关系不能矛盾,就好像你用RMB换日元再换成美刀和直接换成美刀一样,钱数不变……
然后一波乱搞,为了防止精度出问题,我整个运算过程用的是结构体,用分子分母表示
#include <iostream> #include <cstdio> #include <cstring> #include <memory.h> #include <queue> #include <cmath> using namespace std; typedef long long ll; const int N=9; const ll Inf=1e5+1; struct Float { ll z,m; friend bool operator < (Float a,Float b) { return a.z*b.m<a.m*b.z; } friend Float operator * (Float a,Float b) { return (Float){a.z*b.z,a.m*b.m}; } }; struct Graph { int v,nx; Float f; }g[2*N*N]; int cnt,list[N]; Float dis[N],mx=(Float){1,Inf}; int end; bool vis[N]; string a[N],c; int acnt; int n,need,kind; void Add(int u,int v,int z,int m) { g[++cnt]=(Graph){v,list[u],(Float){m,z}};list[u]=cnt; g[++cnt]=(Graph){u,list[v],(Float){z,m}};list[v]=cnt; } bool Check(Float a) { ll b=1.0*a.z/a.m+(a.z%a.m?1:0); return b<Inf; } void SPFA() { queue<int> q; while (!q.empty()) q.pop(); memset(vis,0,sizeof vis); for (int i=1;i<=acnt;i++) dis[i]=(Float){1,Inf}; q.push(kind);dis[kind]=(Float){need,1};vis[kind]=1; while (!q.empty()) { int u=q.front();q.pop(); for (int i=list[u];i;i=g[i].nx) if (dis[g[i].v]<dis[u]*g[i].f) { dis[g[i].v]=dis[u]*g[i].f; if (!vis[g[i].v]) q.push(g[i].v); vis[g[i].v]=1; } vis[u]=0; } } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { int z,m,u=0,v=0; scanf("%d ",&z); cin>>c; cin>>a[0]; for (int j=1;j<=acnt;j++) if (c==a[j]) { u=j; break; } if (!u) u=++acnt,a[acnt]=c; scanf("%d ",&m); cin>>c; for (int j=1;j<=acnt;j++) if (c==a[j]) { v=j; break; } if (!v) v=++acnt,a[acnt]=c; Add(u,v,z,m); } scanf("%d ",&need); cin>>c; for (int i=1;i<=acnt;i++) if (c==a[i]) { kind=i; break; } SPFA(); for (int i=1;i<=acnt;i++) if (Check(dis[i])&&1.0*(1ll*dis[i].z/dis[i].m+(dis[i].z%dis[i].m?1:0))*dis[i].m/dis[i].z<1.0*(1ll*mx.z/mx.m+(mx.z%mx.m?1:0))*mx.m/mx.z&&i!=kind) { mx=dis[i]; end=i; } printf("%lld ",(ll)(1.0*mx.z/mx.m+(mx.z%mx.m?1:0))); cout<<a[end]; return 0; }
在日渐沉没的世界里,我发现了你。