bzoj 3143: [Hnoi2013]游走 高斯消元

本文介绍了一种使用图论解决流量分配问题的方法,通过建立节点和边的关系,计算每个节点期望的流量次数,最终按照期望次数进行流量分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       对每一个点设f[i]为期望从i出发的次数(第一次从1出发不算),那么有:f[n]=0;f[1]-1=Σf[x]((x,i)为一条边);f[x]=Σf[y](x≠1,(x,y)为一条边)。

       然后解出方程,那么得到一条边的期望经过次数,按期望经过次数从大到小一次赋为1~m即可。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define eps 1e-10
#define N 505
using namespace std;

int n,m,d[N];
struct edg{ int x,y; double z; }e[N*N]; double a[N][N];
void solve(){
	int i,j,k; double t;
	for (i=1; i<=n; i++){
		for (j=i; j<=n; j++) if (fabs(a[j][i])>eps) break;
		if (j>n) continue; if (j!=i) swap(a[i],a[j]);
		for (j=i+1; j<=n; j++) if (fabs(a[j][i])>eps){
			t=a[j][i]/a[i][i];
			for (k=i; k<=n+1; k++) a[j][k]-=t*a[i][k];
		}
	}
	for (i=n; i; i--){
		for (j=i+1; j<=n; j++) a[i][n+1]-=a[i][j]*a[j][n+1];
		a[i][n+1]/=a[i][i];
	}
}
bool cmp(edg u,edg v){ return u.z>v.z; }
int main(){
	scanf("%d%d",&n,&m); int i;
	for (i=1; i<=m; i++){
		scanf("%d%d",&e[i].x,&e[i].y);
		d[e[i].x]++; d[e[i].y]++;
	}
	for (i=1; i<=m; i++){
		a[e[i].x][e[i].y]+=1.0/d[e[i].y];
		a[e[i].y][e[i].x]+=1.0/d[e[i].x];
	}
	for (i=1; i<=n; i++) a[n][i]=0;
	for (i=1; i<=n; i++) a[i][i]=-1;
	a[1][n+1]=-1;
	solve();
	for (i=1; i<=m; i++)
		e[i].z=a[e[i].x][n+1]/d[e[i].x]+a[e[i].y][n+1]/d[e[i].y];
	sort(e+1,e+m+1,cmp);
	double ans=0;
	for (i=1; i<=m; i++) ans+=e[i].z*i;
	printf("%.3f\n",ans);
	return 0;
}


by lych

2016.4.6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值