3470: Freda’s Walk
Time Limit: 1 Sec Memory Limit: 128 MB
Description
雨后的Poetic Island空气格外清新,于是Freda和Rainbow出来散步。 Poetic Island的交通可以看作一张n个点、m 边的有向无环图。由于刚下过雨,每条边都有一个积水深度,而恰好Freda 和Rainbow都喜欢踩水玩儿,于是Ta们从某个点出发,选择走向哪条边的概率与该边的积水深度是成正比的。即:如果Freda和Rainbow现在在点u,点u 出发的所有边的积水深度之和为s,从u到v的边积水深度为w,那么Ta们选择走向v的概率就是 w/s。
Ta们会一直走下去,直到到达一个没有出边的点,那么散步的路程长度就是走过的边的数量。更特殊的是,Freda和Rainbow在出发之前还可以选择一条边,在散步过程中无视这条边的存在(当然也可以不选择)。请你帮忙计算一下,Ta 们从0号点出发,散步的路程长度的期望值最大是多少?
Input
第一行两个正整数 n、m。
接下来m行每行三个整数u、v、w,表示从u到v有一条无向边,积水深度为w。
Output
输出Freda和Rainbow散步的路程长度的最大期望值,四舍五入保留六位小数。
Sample Input
4 5
0 1 2
0 2 1
0 3 3
1 3 1
2 3 4
Sample Output
2.000000
HINT
对于 100% 的数据,2<=n<=10000,1<=m<=100000,0<=u,v
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define Maxn 100010
#define Maxm 1000010
struct node{
int u, to, w, nxt, flag;
}ed[Maxm], ted[Maxm];
int head[Maxn], idc;
int sum[Maxn], fed[Maxn];
bool vis[Maxn];
double g[Maxn], f[Maxn];
void adde(int u, int v, int w){
ed[++idc].u = u; ed[idc].to = v; ed[idc].w = w;
ed[idc].nxt = head[u]; head[u] = idc; ed[idc].flag = 1;
ted[idc].u = v; ted[idc].to = u; ted[idc].w = w;
ted[idc].nxt = fed[v]; fed[v] = idc;//建立反向边
}
void dfs2(int u){
if( vis[u] ) return;
vis[u] = 1;
if(u == 0) { g[u] = 1; return;}
for(int i=fed[u]; i; i=ted[i].nxt){
int v = ted[i].to;
dfs2( v );
g[u] += g[v] * ted[i].w * 1.0 / sum[v];//到达每个点的概率
}
}
void dfs(int u){
if( vis[u] ) return;
vis[u] = 1; f[u] = 0;
for(int i=head[u]; i; i=ed[i].nxt)
if( ed[i].flag ){//
int v = ed[i].to;
dfs( v );
f[u] += (f[v] + 1) * ed[i].w * 1.0 / sum[u];
}
return;
}
int main(){
freopen("secretbase.in", "r", stdin);
freopen("secretbase.out", "w", stdout);
int n, m;
scanf("%d%d", &n, &m);
idc = 0;
memset(head, 0, sizeof(head));
for(int i=1; i<=m; i++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
sum[u] += w;
adde(u, v, w);
}
memset(vis, 0, sizeof(vis));
for(int i=0; i<n; i++) g[i] = 0;
for(int i=0; i<n; i++) dfs2( i );
memset(vis, 0, sizeof(vis));
dfs( 0 );
double mx = f[0];
for(int i=1; i<=idc; i++){
int x = ed[i].u, y = ed[i].to;
double cc;
if(sum[x] != ed[i].w)
cc = (f[x]*sum[x]*1.0/(sum[x]-ed[i].w)-(f[y]+1)*ed[i].w*1.0/(sum[x]-ed[i].w))-f[x];
else cc = -f[x];//删掉这条边所做出的贡献
mx = max(mx, f[0] + g[x]*cc);
}
printf("%.6lf\n", mx);
return 0;
}