ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P3232 [HNOI2013]游走

2020-11-11 13:03:29  阅读:271  来源: 互联网

标签:Node 概率 frac int HNOI2013 P3232 pi 游走 include


题目链接

题意分析

我们计算出每一条边经过的概率是多少

然后概率大的边编号小

怎么计算概率 是一个问题

首先 我们存在一条边

这条边的两个端点是\(u,v\)

经过两个端点的概率分别是\(p_u,p_v\)

这两个端点链接的边数分别是\(d_u,d_v\)

那么经过这条边的概率就是\(\frac{p_u}{d_u}+\frac{p_v}{d_v}\)

怎么计算经过一个点的概率 ?

\[p_i=\begin{cases} \sum_{∃(u,i)∈E}\frac{p_u}{d_u}+1\ \ \ (i=1)\\ \sum_{∃(u,i)∈E}\frac{p_u}{d_u}\ \ \ (1<i<n)\\ 0\ \ \ (i=n) \end{cases} \ \]

具体怎么计算 如果使用图论的遍历的话 存在环的情况会特别难搞 而顺序的话也不好处理

但是我们发现对上述状态转移方程加以转化的话 就成了线性方程组

那么我们就可以考虑一下 使用高斯消元法解一下 然后的话就可以求边边 然后编号了

CODE:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define N 510
#define M 1250080
using namespace std;
int n,m;
int in[N];
struct Node
{
	int u,v,id;
	double pi;
	friend bool operator < (const Node &A,const Node &B)
	{return A.pi>B.pi;}
}e[M];
double num[N][N],ans[N];
double lastans;
vector<int> G[N];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d",&e[i].u,&e[i].v);
		in[e[i].u]++;in[e[i].v]++;
		G[e[i].u].push_back(e[i].v);
		G[e[i].v].push_back(e[i].u);
	} 
	for(int i=1;i<n;++i)
	{
		if(i==1) num[1][n]=1;
		for(int j=0;j<(int)G[i].size();++j)
		{
			if(G[i][j]==n) continue;
			num[i][G[i][j]]=-1.0/(double)in[G[i][j]];
		} 
		num[i][i]=1.0;
	}
//	for(int i=1;i<n;++i)
//	 for(int j=1;j<=n;++j)
//	  printf("%.3lf%c",num[i][j],(j==n ? '\n':' '));
	
	for(int k=1;k<n;++k)
	{
		int nowtmp=k;
		for(int i=k+1;i<n;++i)
		if(fabs(num[nowtmp][k])<fabs(num[i][k])) nowtmp=i;
		
		swap(num[nowtmp],num[k]);
		
		double tmp=num[k][k];
		for(int i=k;i<=n;++i) num[k][i]/=tmp;
		
		for(int i=k+1;i<n;++i)
		{
		 tmp=num[i][k];	
		 for(int j=k;j<=n;++j) num[i][j]-=num[k][j]*tmp;	
		}
	}  
//	for(int i=1;i<n;++i)
//	 for(int j=1;j<=n;++j)
//	  printf("%.3lf%c",num[i][j],(j==n ? '\n':' '));
	for(int i=n-1;i>0;--i)
	{
		for(int j=i+1;j<n;++j) num[i][n]-=num[i][j]*ans[j];
		ans[i]=num[i][n];
	}
//	for(int i=1;i<=n;++i) printf("%.3lf%c",ans[i],(i==n ? '\n':' '));
	for(int i=1;i<=m;++i) e[i].pi=(ans[e[i].u]/(double)in[e[i].u]+ans[e[i].v]/(double)in[e[i].v]);
	sort(e+1,e+m+1);
	for(int i=1;i<=m;++i)
	lastans+=(double)i*e[i].pi;
	printf("%.3lf\n",lastans);
	return 0;
}

标签:Node,概率,frac,int,HNOI2013,P3232,pi,游走,include
来源: https://www.cnblogs.com/LovToLZX/p/13958139.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有