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;
}