【期望·高斯消元】HNOI2013 游走

题目传送门

容易想到,应该是算出经过每一条边的期望,然后给期望大的赋小的编号,期望小的赋大的编号。
没有其它奇奇怪怪的附加属性,只是随意地走的话,经过边的期望应该只是和图的长相有关联,也就是只和边两边的结点有关,而且边的数量没有限制,最大可以达到 n 2 n^2 n2的级别,所以我们可以用点的期望来算边的期望。
如果知道了点的期望,那么边的期望就是
点 的 期 望 ∗ 1 这 个 点 的 边 数 点的期望*\frac{1}{这个点的边数} 1(这条边两个端点这么算的和)
那么就要开始求点的期望了
对于每一个点 x x x,设点的期望是 f [ x ] f[x] f[x],与 x x x相邻的有 n u m [ x ] num[x] num[x]条边,相邻的点是 1 至 k 1至k 1k,则有下式:

每一个点都可以列出这样的式子,进行高斯消元就可以解出 f [ ] f[] f[]
特殊地,要注意第一个点和第 n n n个点
"游走"是从点 1 1 1开始,则计算点 1 1 1期望时实际期望应该是原期望+ 1 1 1
到了点 n n n不会继续"游走"了 则若有点和 n n n相连,那么在计算期望时是不需要将其算入的


#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define N 505
int n,m;
double f[N][N],ans[N],q[N*N];
vector<int>G[N];
int F[N*N],T[N*N];
double eps=1e-7;
int rd()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return f*x;
}
double Abs(double x)
{
	if(x>0) return x;
	return -x;
}
void Gauss()
{
	for(int i=1;i<n;i++)
	{
		int r=i;
		for(int j=i+1;j<n;j++)
			if(Abs(f[r][i])<Abs(f[j][i]))
				r=j;
		//找这一列系数最大的那一行 
		//每次丢掉的那个都挪到了上面去 所以从i开始就可以 
		if(i!=r) swap(f[i],f[r]);
		double div=f[i][i];//现在第i行是目标 
		for(int j=i;j<=n;j++)
			f[i][j]/=div;//第j个系数化为1
		for(int j=i+1;j<=n;j++)
		{
			div=f[j][i];
			for(int k=i;k<=n;k++)
				f[j][k]-=f[i][k]*div;
		}
	}
	for(int i=n-1;i>=1;i--)
	{//回带 
		ans[i]=f[i][n];
		for(int j=i+1;j<n;j++)
			ans[i]-=(f[i][j]*ans[j]);
		//ans[i]/=f[i][i];
	}
	return ;
}
bool cmp(double a,double b)
{
	return a>b;
}
int main()
{
	n=rd(),m=rd();
	for(int i=1;i<=m;i++)
	{
		int u=rd(),v=rd();
		G[u].push_back(v);
		G[v].push_back(u);
		F[i]=u,T[i]=v;
	}
	f[1][n]=1.0;//第1个点一开始就在 期望是1 
	for(int i=1;i<n;i++)
	{
		f[i][i]=1.0;
		for(int j=0;j<G[i].size();j++)
			if(G[i][j]!=n)
				f[i][G[i][j]]=-1.0/G[G[i][j]].size();
	}
	Gauss();
	for(int i=1;i<=m;i++)
		q[i]=ans[F[i]]/G[F[i]].size()+ans[T[i]]/G[T[i]].size();
	sort(q+1,q+m+1,cmp);
	double res=0;
	for(int i=1;i<=m;i++)
		res+=q[i]*(1.0*i);
	printf("%.3lf\n",res);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]和引用\[2\]的描述,题目中的影魔拥有n个灵魂,每个灵魂有一个战斗力ki。对于任意一对灵魂对i,j (i<j),如果不存在ks (i<s<j)大于ki或者kj,则会为影魔提供p1的攻击力。另一种情况是,如果存在一个位置k,满足ki<c<kj或者kj<c<ki,则会为影魔提供p2的攻击力。其他情况下的灵魂对不会为影魔提供攻击力。 根据引用\[3\]的描述,我们可以从左到右进行枚举。对于情况1,当扫到r\[i\]时,更新l\[i\]的贡献。对于情况2.1,当扫到l\[i\]时,更新区间\[i+1,r\[i\]-1\]的贡献。对于情况2.2,当扫到r\[i\]时,更新区间\[l\[i\]+1,i-1\]的贡献。 因此,对于给定的区间\[l,r\],我们可以根据上述方法计算出区间内所有下标二元组i,j (l<=i<j<=r)的贡献之和。 #### 引用[.reference_title] - *1* *3* [P3722 [AH2017/HNOI2017]影魔(树状数组)](https://blog.csdn.net/li_wen_zhuo/article/details/115446022)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [洛谷3722 AH2017/HNOI2017 影魔 线段树 单调栈](https://blog.csdn.net/forever_shi/article/details/119649910)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值