比赛没写出来耻辱啊!又看了看邻接表,懂了之后写的。当时因为是50001个数据,如果临街矩阵的话肯定mle,只能用到邻接表,我当时邻接表不是很熟,觉得写不出来就没有写
题意:大致表述为从节点s向节点t传送电力,电力在传送过程中会有所消耗,不同节点之间,电力传送消耗的值有所不同。要求选择一条使得电力消耗最小的线路。如果不能把电力从s点传送到t点,或者电力损失殆尽,则输出IMPOSSIBLE!
如果从s出发,没有到达t的路径,则输出IMPOSSIBLE!
如果存在这样一条路径p = (s,p1,p2,p3,…,pn,t),那么最后到达t的电力为M*(1-b1%)*(1-b2%)*…*(1-bn%)*(1-bn+1%)。即我们需要找到这样一条路径,使得(1-b1%)*(1-b2%)*…*(1-bn%)*(1-bn+1%)最大。
思路:
思路1、我们可以把乘积的形式通过取对数化作连续相加的形式
即log(1-b1%) +…+log(1-bn+1%),由于 log(1-bi%)都是小于0的,我们要求这个式子的最大值就是求每个子式取绝对值的最小值。所以通过取对数在取绝对值的操作,我们可以得到两节点之间新的边权。同时题目也转化为求单源最短路问题。最后注意把结果进行转化。
思路2、直接贪心。类似于Dijkstra算法。我们要求损耗最小,也就是剩余最大。对于每个节点,我们记录起当前可以达到的剩余最大电力。和Dijkstra算法相似,我们这里每次找寻的是尚未标记的拥有最大值的结点,并把这个最大值作为当前结点的最终结果,标记此结点并通过当前结点拓展与之相连的结点。因为从一个结点传输电力到另一个几点,电力的总量是不会增加的。所以,在以后的贪心过程中,不会更新之前已经标记的结点,因为不可能有更大的值。
这样只要求得最后到达t的最大剩余电力就能得出答案。
As we have all known, power will be loss during the transmission. Bob is the chief engineer of the project. He wants to build a transmission line which send power from one node to another node and minimize the power loss at the same time. Now he asks you to help him solve the problem.
4 2 2 50 3 70 2 1 30 4 20 2 1 10 4 40 0 1 4 100
60.00HintIn the sample, the best transmission line is 1 -> 2 -> 4, loss power is 100 * 50% + 100 * (100%-50%)*20% = 60.00
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int nv=50006;
const int ne=2505010;
#define data 100000000
int n;
double M;
struct Dijkstra
{
int nn,size;
double dis[nv];
int mark[nv],head[nv];
struct edge{
int v,next;
double w;
edge(){}
edge(int v,int next,double w):v(v),next(next),w(w){}
}ee[ne];
inline void init(int nx)
{
nn=nx;size=0;
memset(head,-1,sizeof(head));
}
inline void insert(int u,int v,double w)
{
ee[size]=edge(v,head[u],w);
head[u]=size++;
}
void spfa(int src,int n)
{
memset(mark,0,sizeof(mark));
queue<int>q;
for(int i=1;i<=n;i++)
{
dis[i]=data;
}
dis[src]=0;
q.push(src);
mark[src]=true;
while(!q.empty())
{
int uu=q.front();
q.pop();
mark[uu]=0;
for(int i=head[uu];i!=-1;i=ee[i].next)
{
int v=ee[i].v;
if(dis[v] > dis[uu]+(M-dis[uu])*((double)ee[i].w/100))//跟最短路的思想差不多,不断松弛dis[],当下个节点的消耗量小于上个节点时就更新
{
dis[v] =dis[uu]+(M-dis[uu])*((double)ee[i].w/100);
if(!mark[v])
{
q.push(v);
mark[v]=1;
}
}
}
}
return ;
}
}g;
int main()
{
int m,destination,start,end,weight;
while(scanf("%d",&n)!=EOF)
{
g.init(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&destination,&weight);
g.insert(i,destination,weight);
}
}
scanf("%d%d%lf",&start,&end,&M);
g.spfa(start,n);
if(g.dis[end]<data)
printf("%.2lf\n",g.dis[end]);
else
printf("IMPOSSIBLE!\n");
}
return 0;
}