题解:
不难发现,在有向图中,从起点出发,越往后达到每个点的概率越低,就是说一个点的下一个点的概率一定不会大于上一个点。
那么用贪心的思想,每次选择概率最大的一点放陷阱,这样期望加的也是最多的。
先BFS处理出所有点的概率,然后将概率从大到小排序,先算出不放陷阱的期望,然后在加上T个陷阱放上去之后的期望,注意起点不能放陷阱。复杂度O(m + nlogn),另外这份代码在OJ上跑有精度问题只有95分,在Linux下测却没有这样的问题。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cctype>
#include<climits>
#define MAXA 100500
using namespace std;
int Head[MAXA],cnt;
struct Rx_Graph {
int next,to;
long double w;
}Edge[MAXA];
void Add(int u,int v,long double w) {
Edge[++cnt].next = Head[u];
Edge[cnt].to = v;
Edge[cnt].w = w;
Head[u] = cnt;
}
bool Cmp(const long double &a,const long double &b) {
return a > b;
}
int n,m,UpDamage,Start,T,Trapper[MAXA],u,v,k,Q[MAXA],h = 1,t = 1;
long double c,Ans,Point[MAXA];
int main() {
// freopen("trap.in","r",stdin);
// freopen("trap.out","w",stdout);
scanf("%d %d %d %d %d",&n,&m,&UpDamage,&Start,&T);
for(int i=1;i<=n;i++)
scanf("%d",&Trapper[i]);
for(int i=1;i<=m;i++) {
scanf("%d %d %Lf",&u,&v,&c);
Add(u,v,c);
}
Q[t++] = Start;
Point[Start] = 1.0000;
while(h != t) {
k = Q[h];
h++;
for(int i=Head[k];i;i=Edge[i].next) {
int j = Edge[i].to;
Point[j] += Point[k] * Edge[i].w;
Edge[i].w = Point[j];
Q[t++] = j;
}
}
for(int i=1;i<=n;i++)
Ans += (long double)Trapper[i] * Point[i];
sort(Point + 1,Point + n + 1,Cmp);
for(int i=2;i<=T+1;i++)
Ans += (long double)UpDamage * Point[i];
printf("%.3Lf",Ans);
}
/*
4 3 30 1 1
10 50 20 10
1 2 0.80
1 3 0.10
2 4 0.60
8 7 15 1 1
21 35 15 65 98 12 33 15
1 2 0.20
1 3 0.56
3 8 0.73
3 7 0.11
3 4 0.13
2 6 0.10
2 5 0.80
*/