首页 > 代码库 > BZOJ 2419 电阻 高斯消元

BZOJ 2419 电阻 高斯消元

题目大意:给定n个点,一些点之间有电阻相连,求1~n的等效电阻

首先我们设电流为1A 终点电势为零 点i的电势为Ui

由于电流是流 显然对于每个点(点1和点n除外) 有总流入等于总流出 即

Σ(Ui-Uj)/Rij=0 (i!=1,i!=n)
Σ(U1-Uj)/R1j=1
Σ(Un-Uj)/Rnj=-1
Un=0

联立方程组高斯消元即可 最后输出点1的电势就是答案

注意自环要无视 重边要用倒数和缩成一条 我用了电导所以直接加就行

科普:电导 电阻的倒数 G=1/R=I/U 在两个点之间并联多个电阻时G总=ΣGi 两点间断路时G=0 短路时G=+∞

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 510
using namespace std;
int n,m;
double map[M][M],f[M][M],ans[M];
void Initialize()
{
	memset(map,0,sizeof map);
	memset(f,0,sizeof f);
}
void Gauss_Elimination()
{
	int i,j,k;
	for(i=1;i<=n;i++)
	{
		k=0;
		for(j=i;j<=n;j++)
			if( fabs(f[j][i])>fabs(f[k][i]) )
				k=j;
		for(j=1;j<=n+1;j++)
			swap(f[i][j],f[k][j]);
		for(j=i+1;j<=n;j++)
		{
			double temp=f[j][i]/f[i][i];
			for(k=i;k<=n+1;k++)
                f[j][k]-=f[i][k]*temp;
		}
	}
	for(i=n;i;i--)
	{
		for(j=n;j>i;j--)
			f[i][n+1]-=ans[j]*f[i][j];
		ans[i]=f[i][n+1]/f[i][i];
	}
}
int main()
{
	int i,j,x,y,r;
	while(cin>>n>>m)
	{
		Initialize();
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&x,&y,&r);
			map[x][y]+=1.0/r;map[y][x]+=1.0/r;
		}
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				f[i][i]+=map[i][j],f[i][j]-=map[i][j];
		f[1][n+1]=1;
		f[n][n+1]=-1;
		f[n][n]+=1.0;
		Gauss_Elimination();
		printf("%.2lf\n",ans[1]);
	}
}


BZOJ 2419 电阻 高斯消元