题解 P1576 【最小花费】

「QQ红包」

2017-09-07 13:13:48

Solution

其实是最短路. 把起点和终点反过来求最短路. 就是松弛操作改一改就好. ```cpp #include<bits/stdc++.h> using namespace std; int read() { char s; int k=0,base=1; while((s=getchar())!='-'&&s!=EOF&&!(s>='0'&&s<='9')); if(s==EOF)exit(0); if(s=='-')base=-1,s=getchar(); while(s>='0'&&s<='9') { k=k*10+(s-'0'); s=getchar(); } return k*base; } void write(int x) { if(x<0) { putchar('-'); write(-x); } else { if(x/10)write(x/10); putchar(x%10+'0'); } } int n,m,X,Y,Z,id,s,t,u,v; int to[4000010]; int wi[4000010]; int ne[4000010]; int po[4000010]; int vis[4010]; double dis[4000]; queue<int> q; inline void add(int x,int y,int z) { id++; to[id]=y; wi[id]=z; ne[id]=po[x]; po[x]=id; } int main() { n=read(); m=read(); for (int i=1;i<=m;i++) { X=read();Y=read();Z=read(); add(X,Y,Z);//加双向边 add(Y,X,Z); } t=read();s=read();//起点和终点反一下 for (int i=0;i<=n+1;i++) dis[i]=23333333.0; q.push(s); dis[s]=100.0; vis[s]=1; while (!q.empty()) { u=q.front();q.pop(); vis[u]=0; for (int i=po[u];i;i=ne[i]) { v=to[i]; if (dis[v]>(double)(dis[u])/(1-0.01*wi[i]))//松弛操作 { dis[v]=(double)(dis[u])/(1-0.01*wi[i]); if (vis[v]==0)//入队 { vis[v]=1; q.push(v); } } } } printf("%.8lf",dis[t]);//输出 return 0; } ```