题目←
思路:
求距终点距离的递推式:
dis[f] = dis[t] + l[i].v
加上期望
E[f] = E[t] +l[i].v
这是对于f只有t一条出边的情况
多条出边时,设G为f所有出边的集合
#include
#include
#include
using namespace std;
double E[200000];
int n,m;
struct edge{
int f,t;
double v;
}l[200000 << 1];
int head[200000],next[400000],tot;
void init(int n){
for(int i = 1;i <= n;i ++){
head[i] = -1;
}
}
void build(int f,int t,double v){
l[++tot] = (edge){f,t,v};
next[tot] = head[f];
head[f] = tot;
}
int a,b;
double c;
int ru[200000],topo[200000],chu[200000];
int hd,tl;
int main(){
scanf("%d%d",&n,&m);
init(n);
for(int i = 1;i <= m;i ++){
scanf("%d%d%lf",&a,&b,&c);
build(a,b,c);
ru[b] ++;
chu[a] ++;
}
for(int i = 1;i <= n;i ++){
if(!ru[i]){
topo[tl ++] = i;
}
}
while(hd != tl){
int u = topo[hd];
hd ++;
for(int i = head[u];i != -1;i = next[i]){
int t = l[i].t;
ru[t] --;
if(!ru[t]){
topo[tl ++] = t;
}
}
}
for(int i = n - 1;i >= 0;i --){
int u = topo[i];
if(head[u] == -1)continue;
for(int j = head[u];j != -1;j = next[j]){
int t = l[j].t;
E[u] += (E[t] + l[j].v)/chu[u];
}
}
printf("%.2lf",E[1]);
}
注意最后不会到达n的边也是对答案有贡献的(可能被走过)
又看了某大佬的解法……分别计算每条边对答案的贡献
dp[f]->f可能被经过的次数
设 e∈Gf ,则e对答案贡献为
#include
#include
#include
using namespace std;
double E[200000];
int n,m;
struct edge{
int f,t;
double v;
}l[200000 << 1];
int head[200000],next[400000],tot;
void init(int n){
for(int i = 1;i <= n;i ++){
head[i] = -1;
}
}
void build(int f,int t,double v){
l[++tot] = (edge){f,t,v};
next[tot] = head[f];
head[f] = tot;
}
int a,b;
double c;
int ru[200000],topo[200000],chu[200000];
int hd,tl;
double ans;
int main(){
scanf("%d%d",&n,&m);
init(n);
for(int i = 1;i <= m;i ++){
scanf("%d%d%lf",&a,&b,&c);
build(a,b,c);
ru[b] ++;
chu[a] ++;
}
for(int i = 1;i <= n;i ++){
if(!ru[i]){
topo[tl ++] = i;
}
}
E[1] = 1.00;
while(hd != tl){
int u = topo[hd];
hd ++;
for(int i = head[u];i != -1;i = next[i]){
int t = l[i].t;
ru[t] --;
E[t] += E[u]/chu[u];
ans += E[u]*l[i].v/chu[u];
if(!ru[t]){
topo[tl ++] = t;
}
}
}
printf("%.2lf",ans);
}