死宅与陷阱

题解:

不难发现,在有向图中,从起点出发,越往后达到每个点的概率越低,就是说一个点的下一个点的概率一定不会大于上一个点。

那么用贪心的思想,每次选择概率最大的一点放陷阱,这样期望加的也是最多的。

先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
*/

猜你喜欢

转载自blog.csdn.net/qq_41513352/article/details/83215100