[HDU3976]Electric resistance(电阻)(信竞&物竞)(高斯消元)

题面

Problem Description

Now give you a circuit who has n nodes (marked from 1 to n) , please tell abcdxyzk the equivalent resistance of the circuit between node 1 and node n. You may assume that the circuit is connected. The equivalent resistance of the circuit between 1 and n is that, if you only consider node 1 as positive pole and node n as cathode , all the circuit could be regard as one resistance . (It's important to analyse complicated circuit ) At most one resistance will between any two nodes.

给你一个无向连通图(电路图)

每一条边的边权为这条边的电阻,点1是正极,点n是负极。

求整个电路的等效电阻。

Input

In the first line has one integer T indicates the number of test cases. (T <= 100)

T组数据

Each test first line contain two number n m(1<n<=50,0<m<=2000), n is the number of nodes, m is the number of resistances.Then follow m lines ,each line contains three integers a b c, which means there is one resistance between node a and node b whose resistance is c. (1 <= a,b<= n, 1<=c<=10^4) You may assume that any two nodes are connected!

n m
u1 v1 w1(R)
......
um vm wm(R)

Output

for each test output one line, print "Case #idx: " first where idx is the case number start from 1, the the equivalent resistance of the circuit between 1 and n. Please output the answer for 2 digital after the decimal point .

Case #idx: answer_x(double)
......

题解

不妨先随便假设电源电压为一个值U,已知量为边的电阻,我们要设未知量来高斯消元解方程。

设每个点的电流有点麻烦,我们设电压。

由于电压指导体两端的电压,不能说某个点的电压,于是我们设U[i]为 以i和n为两端的电路的电压

显然,U[1] = U,U[n] = 0,U[i]是个未知数。

若电流从u流到v,那么U[u]一定大于U[v]。

由于流入一个点 i 的电流等于流出一个点的电流,

\sum I_{in}=\sum I_{out}

\sum I_{in}-\sum I_{out}=\sum I_{out}-\sum I_{in}=0

由于

\sum I_{out}=\sum \frac{U_{i}-U_{to}}{R_{i\rightarrow to}}(U_{to}<U_i)

-\sum I_{in}=\sum - \frac{U_{from}-U_i}{R_{from\rightarrow i}}(U_{from}>U_i)=\sum \frac{U_i-U_{from}}{R_{from\rightarrow i}}(U_{from}>U_i)

那么合并一下,\sum \frac{U_i-U_j}{R_{i,j}}(U_i\neq U_j)=0

这就是方程组中的一个方程,用高斯消元可以把U[...]都求出来,可以证明一定有解。

最后通过点1连接的电阻算出干路电流,再通过欧姆定律R=\frac{U}{I}算出等效电阻。

这里有一份很不错的高斯消元板子

CODE

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<algorithm>
#define LL long long
#define MAXN 105
#define DB double
#define lowbit(x) ((-x & x))
#define rg register
#define eps (1e-8)
using namespace std;
inline LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
	return x * f;
}
LL n;
LL m,i,j,s,o,k;
bool cmp(DB a,DB b) {
	if(a-b>eps) return 1;
	if(a-b<-eps) return -1;
	return 0;
}
bool gauss(int n,DB a[][MAXN]) {
	bool flag=1;
	for(int i = 1;i <= n;i ++) {
		int maxi = i;
		for(int j = i+1;j <= n;j ++) {
			if(cmp(a[maxi][i],a[j][i]) == -1) {
				maxi = j;
			}
		}
		swap(a[maxi],a[i]);
		if(cmp(a[i][i],0.0) == 0) {
			flag = 0;continue;
		}
		for(int j = 1;j <= n;j ++) {
			if(i==j || cmp(a[j][i],0) == 0) continue;
			for(int k = i+1;k <= n+1;k ++) {
				a[j][k] -= a[i][k] * a[j][i]/a[i][i];
			}
			a[j][i] = 0;
		}
	}
	return flag;
}
int gauss_final(int n,DB a[][MAXN],DB *b) {
	if(!gauss(n,a)) {
		for(int i = 1;i <= n;i ++) {
			bool flag = 0;
			for(int j = 1;j <= n;j ++) {
				if(cmp(a[i][j],0) != 0) {
					flag = 1;
				}
			}
			if(!flag && cmp(a[i][n+1],0) != 0) return -1;
		}
		return 0;
	}
	for(int i = 1;i <= n;i ++) {
		b[i] = a[i][n+1]/a[i][i];
	}
	return 1;
}
DB a[MAXN][MAXN];
DB U[MAXN];
DB g[MAXN];
queue<int> q;
int main() {
	int T = read(),idx=0;
	while(T --) {
		n = read();m = read();
		memset(a,0,sizeof(a));
		memset(U,0,sizeof(U));
		memset(g,0,sizeof(g));
		U[1] = 100.0;U[n] = 0;
		while(!q.empty()) q.pop();
		for(int i = 1;i <= m;i ++) {
			s = read();o = read();k = read();
			if(s>o) swap(s,o);
			int t = o;
			if(s == 1) q.push(o),g[o] = k*1.0;
			if(s!=1&&s!=n) {
				a[s-1][s-1] += 1.0/(DB)k;
				if(t!=1&&t!=n) {
					a[s-1][t-1] -= 1.0/(DB)k;
				}
				else if(t==1) {
					a[s-1][n-1] += 100.0/(DB)k;
				}
			}
			if(t!=1&&t!=n) {
				a[t-1][t-1] += 1.0/(DB)k;
				if(s!=1&&s!=n) {
					a[t-1][s-1] -= 1.0/(DB)k;
				}
				else if(s==1) {
					a[t-1][n-1] += 100.0/(DB)k;
				}
			}
		}
		gauss_final(n-2,a,U+1);
		DB I = 0.0;
		while(!q.empty()) {
			int v = q.front();
			q.pop();
			I += (U[1] - U[v]) / g[v];
		}
		printf("Case #%d: %.2lf\n",++idx,U[1]/I);
	}
	return 0;
}

 

posted @ 2020-01-02 20:02  DD_XYX  阅读(153)  评论(0)    收藏  举报