2019南京网络赛D题 Robots

题目链接:https://nanti.jisuanke.com/t/41301
每个点概率相等的转移到下一个点或停在原地,转移的消耗为当前的时间。
先考虑对于每个点到达终点的期望天数,设x为点i的出边数
d a y [ i ] = ∑ i → j d a y [ j ] + 1 x + 1 + d a y [ i ] + 1 x + 1 = ∑ i → j d a y [ j ] x + 1 + d a y [ i ] x + 1 + 1 d a y [ i ] = ∑ i → j d a y [ j ] x + x + 1 x \begin{aligned} day[i] &= \sum_{i\rightarrow j}\frac{day[j]+1}{x+1} +\frac{day[i]+1}{x+1} \\ &= \sum_{i\rightarrow j}\frac{day[j]}{x+1} +\frac{day[i]}{x+1} +1\\ \end{aligned}\\ day[i]=\sum_{i\rightarrow j}\frac{day[j]}{x} + \frac{x+1}{x} day[i]=ijx+1day[j]+1+x+1day[i]+1=ijx+1day[j]+x+1day[i]+1day[i]=ijxday[j]+xx+1
计算期望消耗的方法与计算期望天数的方法相同(移动一步增加一天,增加当前天数的消耗)
c o s t [ i ] = ∑ i → j c o s t [ j ] + d a y [ j ] + 1 x + 1 + c o s t [ i ] + d a y [ i ] + 1 x + 1 = ∑ i → j c o s t [ j ] x + 1 + ∑ i → j d a y [ j ] x + 1 + c o s t [ i ] x + 1 + d a y [ i ] x + 1 + 1 = ∑ i → j c o s t [ j ] x + 1 + ( x x + 1 d a y [ i ] − 1 ) + c o s t [ i ] x + 1 + d a y [ i ] x + 1 + 1 = ∑ i → j c o s t [ j ] x + 1 + c o s t [ i ] x + 1 + d a y [ i ] c o s t [ i ] = ∑ i → j c o s t [ j ] x + ( x + 1 ) d a y [ i ] x \begin{aligned} cost[i] &= \sum_{i\rightarrow j}\frac{cost[j]+day[j]+1}{x+1} +\frac{cost [i]+day[i]+1}{x+1} \\ &= \sum_{i\rightarrow j}\frac{cost[j]}{x+1}+ \sum_{i\rightarrow j}\frac{day[j]}{x+1}+\frac{cost[i]}{x+1} +\frac{day[i]}{x+1} +1\\ &= \sum_{i\rightarrow j}\frac{cost[j]}{x+1}+(\frac{x}{x+1}day[i]-1)+\frac{cost[i]}{x+1} +\frac{day[i]}{x+1} +1\\ &=\sum_{i\rightarrow j}\frac{cost[j]}{x+1}+\frac{cost[i]}{x+1} +day[i] \\ \end{aligned}\\ cost[i]=\sum_{i\rightarrow j}\frac{cost[j]}{x} + \frac{(x+1)day[i]}{x} cost[i]=ijx+1cost[j]+day[j]+1+x+1cost[i]+day[i]+1=ijx+1cost[j]+ijx+1day[j]+x+1cost[i]+x+1day[i]+1=ijx+1cost[j]+(x+1xday[i]1)+x+1cost[i]+x+1day[i]+1=ijx+1cost[j]+x+1cost[i]+day[i]cost[i]=ijxcost[j]+x(x+1)day[i]
注意转移的时候按拓扑序倒序
AC代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000500
#define INF 0x3f3f3f
#define ll long long
#define cin(x) scanf("%d",&x)
#define cout(x) printf("%d\n",x)
double day[maxn],ans[maxn];
ll T, n, m, u, v;
ll z1,nxt1[maxn],fir1[maxn], cnt1[maxn], b[maxn] ,nn;
ll z2,nxt2[maxn],fir2[maxn], cnt2[maxn];
struct nodes{
	ll u,v;
}edges1[maxn],edges2[maxn];
void link1(ll u,ll v){
	edges1[++z1].u=u;
	edges1[z1].v=v;
	cnt1[v]++;
	nxt1[z1]=fir1[u];
	fir1[u]=z1;
}
void link2(ll u,ll v){
	edges2[++z2].u=u;
	edges2[z2].v=v;
	cnt2[u]++;
	nxt2[z2]=fir2[v];
	fir2[v]=z2;
}
int main(){
	cin(T);
	while(T--) {
		memset(ans, 0.0, sizeof(ans));
		memset(day, 0.0, sizeof(day));
		memset(cnt1, 0, sizeof(cnt1));
		memset(cnt2, 0, sizeof(cnt2));
		memset(fir1, 0, sizeof(fir1));
		memset(fir2, 0, sizeof(fir2));
		memset(nxt1, 0, sizeof(nxt1));
		memset(nxt2, 0, sizeof(nxt2));
		memset(b, 0, sizeof(b));
		scanf("%lld%lld", &n, &m);
		z1 = 0,z2 = 0,nn = n;
		for(int i = 1; i <= m; i++) {
			scanf("%lld%lld", &u, &v);
			link1(u, v);
			link2(u, v);
		}
		queue<int> que;
		for(int i=1;i<=n;i++) if(!cnt1[i]) que.push(i);
		while(!que.empty()){
			int head=que.front();
			b[nn--]=head;
			int tmp = head;
			que.pop();
			for(int i=fir1[head];i;i=nxt1[i]){
				int v=edges1[i].v;
				cnt1[v]--;
				if(!cnt1[v]){
					que.push(v);
				} 
			}
		}
		day[n]=0;
		for(int j=1;j<=n;j++){
			int tail = b[j];
			if(tail!=n){
				day[tail]+=double(cnt2[tail]+1);
				day[tail]/= cnt2[tail];
			}
			for(int i=fir2[tail];i;i=nxt2[i]){
				int u=edges2[i].u;
				day[u] += day[tail];
			}
		}
		ans[n]=0;
		for(int j=1;j<=n;j++){
			int tail = b[j];
			if(tail!=n){
				ans[tail] += day[tail]*double(cnt2[tail]+1);
				ans[tail] /= cnt2[tail];
			}
			for(int i=fir2[tail];i;i=nxt2[i]){
				int u=edges2[i].u;
				ans[u] += ans[tail];
			}
		}
		printf("%.2f\n", ans[1]);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值