http://acm.hdu.edu.cn/showproblem.php?pid=4318
昨天比赛的时候看的这一题,感觉是最短路(PIAOYI竟然说这不是最短路,是深搜,必须又吵了一架),再加上这几天正在研究最短路,轻车熟路就用SPFA开始写起来了,写了一会儿,写出来了,测试样例也过了,提交,wa了,修改一下再交.......一直wa了17次。
今天上午,听洛神讲解了这一题,顿悟啊
变相的最短路问题,根据题意是求M-M(1-a%)(1-%b)(1-c%)(....)的最小值,即最小消耗,M表示起初的电量
M为定值,问题可以转化为求(1-a%)(1-%b)(1-c%)(....)的最大值。注意下面的思想
log((1-a%)(1-%b)(1-c%)(....))=log((1-a%))+log((1-b%))+log((1-c%))....... 将乘法换成加法
因为log((1-a%))的值均为负值,故-log((1-a%))的值越小,log((1-a%))的值越大,于是问题就转化为以-log((1-a%))为线路权值的最短路问题
#include<stdio.h> #include<vector> #include<queue> #include<math.h> #define MAX 50005 #define INF 1<<27 using namespace std; struct node { int v; double w; }; vector<node> g[MAX]; queue<int> q; int n; void spfa(int beg,int end,int sum) { bool flag[MAX]; int i; double path[MAX]; for(i=1;i<=n;i++) { path[i]=INF; flag[i]=0; } flag[beg]=1; path[beg]=0; q.push(beg); while(!q.empty()) { int k=q.front(); q.pop(); flag[k]=0; for(i=0;i<g[k].size();i++) { int v=g[k][i].v; double w=g[k][i].w; if(path[v]>path[k]+w) { path[v]=path[k]+w; if(!flag[v]) { flag[v]=1; q.push(v); } } } } if(int(path[end])>=sum||path[end]>100000) printf("IMPOSSIBLE!\n"); else printf("%.2lf\n",sum-sum/exp(path[end])); //exp()是以自然对数e为底的指数函数 } int main() { int m,i,a,b,end,beg,sum; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) g[i].clear(); for(i=1;i<=n;i++) { scanf("%d",&m); while(m--) { scanf("%d%d",&a,&b); node t; t.v=a;t.w=-log(1.0-b/100.0); g[i].push_back(t); } } scanf("%d%d%d",&beg,&end,&sum); spfa(beg,end,sum); } return 0; }