【题解】CJOI2019 Trade (最短路+性质)

【题解】CJOI2019 Trade (最短路+性质)

如何评价CJ中学某黄姓选手喜欢嘴巴切题的行为?

十一点过十分开始写这道题...差一点点写完时有人催我收卷了

【问题描述】

\(2020\)年,资本主义世界的第\(p\)次金融危机爆发。
远在天涯海角的某皿煮国家也受到了一定的影响。
为了加快经济发展速度,该国政府打算在全国大规模降低地方关税。
降税后,带\(x\)万元到达一个地区,只要交\(1\)万元的税。
然而,一些地区的行政长官抗拒这条指令,他们宣布将维持原来的税率,即带\(x\)万元到达这些地区,需交\(\lceil\frac{x}{k}\rceil\)万元的税。
整个国家的各地区通过\(m\)条道路相互联通。
现在一个商人要带钱从\(s\)地到达\(t\)地。他希望,交完所有的税,到达\(t\)地区时,钱的总量应不少于\(w\)万元。那么请你帮他算算,他出发时最少应带多少钱?
(不需要向地区\(s\)交税)

显然从\(T\)开始往回推,由于降税的城市很好搞,现在就是不降税的城市

往回推,加入原来是从\(u->v\),现在我知道\(v\)的权值,求\(u\)\(dis\)

解一个关于\(x\)的方程
\[ x-\lceil \dfrac x k \rceil=b \]
解出来
\[ x=\lceil \dfrac {kb} {k-1}\rceil \]

由于\(dis\)数组将会单调递增,所以可以贪心的dij

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

const int maxn=5e5+5;
struct E{
      int to,nx,w;
      E(){to=nx=w=0;}
      E(const int&a,const int&b,const int&c){to=a;nx=b;w=c;}
}e[maxn<<2];
int head[maxn];
int cnt;
int S,T,W;
int n,m,k;
int j[maxn];

inline void add(const int&fr,const int&to,const int&f){
      int w=-1;
      if(!j[fr]) w=k;
      e[++cnt]=E(to,head[fr],w);
      head[fr]=cnt;
      if(f)add(to,fr,0);
}

ll d[maxn];
int last[maxn];
const ll inf=2e17;
typedef pair < ll , int > Pll;
priority_queue < Pll , vector < Pll > , greater < Pll > > q;

inline int getw(const ll&x,const ll&mu){
      if(mu==-1)return x+1;
      return (x*mu)/(mu-1LL)+bool((x*mu)%(mu-1));
}

inline int spfa(){
      for(register int t=1;t<=n;++t) d[t]=inf;
      d[T]=W;
      q.push(make_pair(d[T],T));
      while(q.size()){
        register auto now=q.top();
        q.pop();
        if(now.second==S)break;
        for(register int t=head[now.second],t1;t;t=e[t].nx){
          t1=getw(d[now.second],e[t].w);
          if(d[e[t].to]>t1){
            d[e[t].to]=t1;
            last[e[t].to]=now.second;
            q.push(make_pair(d[e[t].to],e[t].to));
          }
        }
      }
      return d[S];
}

int main(){
      //freopen("trade.in","r",stdin);
      //freopen("trade.out","w",stdout);
      n=qr();m=qr();k=qr();
      for(register int t=1;t<=n;++t) j[t]=qr();
      for(register int t=1;t<=m;++t) add(qr(),qr(),1);
      S=qr();T=qr();W=qr();
      printf("%d\n%d",spfa(),S);
      for(register int t=last[S];t;t=last[t])
        printf("->%d",t);
      return 0;
}

猜你喜欢

转载自www.cnblogs.com/winlere/p/11302678.html