HDU 4318 Power transmission

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


 

你可能感兴趣的:(HDU 4318 Power transmission)