洛谷 1576 最小花费
【题解】
用最短路算法求A到B被扣除的最小百分比即可。稍微修改一下最短路的更新方式即可。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #define LL long long 6 #define rg register 7 #define N 2010 8 #define M 100010 9 using namespace std; 10 int n,m,tot,last[N],pos[N],from[N],rec[N][N]; 11 double dis[N],ans=1; 12 struct edge{ 13 int to,pre; double dis; 14 }e[M<<1]; 15 struct heap{ 16 int poi; double dis; 17 }h[N]; 18 inline int read(){ 19 int k=0,f=1; char c=getchar(); 20 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 21 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 22 return k*f; 23 } 24 inline void up(int x){ 25 int fa; 26 while((fa=(x>>1))&&h[fa].dis>h[x].dis){ 27 swap(h[x],h[fa]),swap(pos[h[x].poi],pos[h[fa].poi]); 28 x=fa; 29 } 30 } 31 inline void down(int x){ 32 int son; 33 while((son=x<<1)<=tot){ 34 if(son<tot&&h[son].dis>h[son+1].dis) son++; 35 if(h[son].dis<h[x].dis){ 36 swap(h[x],h[son]); swap(pos[h[x].poi],pos[h[son].poi]); 37 x=son; 38 } 39 else return; 40 } 41 } 42 inline void dijkstra(int x){ 43 for(rg int i=1;i<=n;i++) dis[i]=1000000; 44 h[tot=pos[x]=1]=(heap){x,dis[x]=0}; 45 while(tot){ 46 int now=h[1].poi; h[1]=h[tot--]; if(tot) down(1); 47 for(rg int i=last[now],to;i;i=e[i].pre) 48 if(dis[to=e[i].to]>dis[now]+(1-dis[now])*e[i].dis){ 49 dis[to]=dis[now]+(1-dis[now])*e[i].dis; 50 from[to]=now; 51 if(!pos[to]) h[pos[to]=++tot]=(heap){to,dis[to]}; 52 else h[pos[to]].dis=dis[to]; 53 up(pos[to]); 54 } 55 pos[now]=0; 56 } 57 } 58 int main(){ 59 n=read(); m=read(); 60 for(rg int i=1;i<=m;i++){ 61 int u=read(),v=read(),d=rec[u][v]=rec[v][u]=read(); 62 e[++tot]=(edge){v,last[u],d*1.0/100}; last[u]=tot; 63 e[++tot]=(edge){u,last[v],d*1.0/100}; last[v]=tot; 64 } 65 int s=read(),t=read(); 66 dijkstra(s); 67 int last=from[t]; 68 while(last){ 69 ans*=(1-rec[last][t]*1.0/100); 70 t=last; last=from[t]; 71 // printf("%.8f\n",100*1.0/ans); 72 } 73 printf("%.8f\n",100*1.0/ans); 74 return 0; 75 }
dijkstra的更新方式可以改为dis[to]=dis[now]+(1-dis[now])*e[i].dis.