Electric resistance
题意:已知一个串并联电阻串有n个结点,m种连接关系(u, v, r)表示u结点到v结点存在一个电阻r,求1结点到n结点的等效电阻
题解:高斯消元浮点型,分别设每个节点的电势为xi,我们假设流入1结点的电流为1,然后对每个结点列一个kcl方程,因为这种方式只能算出每两个结点的电势差,所以我们需要给任意一个结点的电势赋值,从而确定其它结点的电势。最后运用高斯消元解方程(需浮点型的高斯消元),最终的等效电阻就是结点n和结点1的电势差除以流入的电流。
//#include"bits/stdc++.h"
//#include<unordered_map>
//#include<unordered_set>
#include<iostream>
#include<sstream>
#include<iterator>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<bitset>
#include<climits>
#include<queue>
#include<iomanip>
#include<cmath>
#include<stack>
#include<map>
#include<ctime>
#include<new>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define MT(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f;
const int O = 1e6;
const int mod = 1e6 + 3;
const int maxn = 51;
const double PI = acos(-1.0);
const double E = 2.718281828459;
const double eps=1e-7;
double x[maxn]; // 方程的解
bool free_x[maxn]; // 不确定的变量
int sgn(double x) { return (x > eps) - (x < -eps ); }
// 高斯消元法 (0表示无解,1表示唯一解,大于1表示无穷解,并返回自由变元的个数)
int gauss(double a[maxn][maxn], int equ, int var) {
int i, j, k, col = 0;
int free_x_num, free_index;
memset(free_x,true,sizeof(free_x));
for(k=0; k<equ && col<var; k++, col++)
{
int max_r = k;
for(i=k+1; i<equ; i++)
if(sgn(fabs(a[i][col]) - fabs(a[max_r][col])) > 0) max_r=i;
if(max_r != k)// 与第k行交换.
for(j=k; j<var+1; j++) swap(a[k][j], a[max_r][j]);
// 说明该col列第k行以下全是0了,则处理当前行的下一列.
if(sgn(a[k][col])==0) { k--; continue; }
for(i=k+1; i<equ; i++) // 枚举要删去的行.
{
if (sgn(a[i][col]) != 0) {
double temp = a[i][col] / a[k][col];
for (j = col; j < var + 1; j++)
a[i][j] = a[i][j] - a[k][j] * temp;
}
}
}
for(int i=k; i<equ; i++)
if (sgn(a[i][col]) != 0) return 0;
if(k < var)
{
for(i=k-1; i>=0; i--)
{
free_x_num = 0;
for (j = 0; j < var; j++)
if (sgn(a[i][j]) != 0 && free_x[j])
free_x_num++, free_index = j;
if (free_x_num > 1) continue;
double temp = a[i][var];
for (j = 0; j < var; j++)
if (sgn(a[i][j]) != 0 && j != free_index)
temp -= a[i][j] * x[j];
x[free_index] = temp / a[i][free_index];
free_x[free_index] = 0;
}
return var - k;
}
for (i=var-1;i>=0;i--)
{
double temp = a[i][var];
for (j = i + 1; j < var; j++)
if (sgn(a[i][j]) != 0)
temp -= a[i][j] * x[j];
x[i] = temp / a[i][i];
}
return 1;
}
int main(){
int T, l = 0; scanf("%d", &T);
double a[maxn][maxn];
while( T -- ){
int n, m; cin >> n >> m;
for(int i=0; i<=n; i++) for(int j=0; j<=n; j++) a[i][j] = 0.0;
// 确定等式左边的系数
for(int i=0; i<m; i++) {
int u, v, x; cin >>u >> v >> x;
u --; v --;
a[u][u] -= 1.0 / x;
a[u][v] += 1.0 / x;
a[v][v] -= 1.0 / x;
a[v][u] += 1.0 / x;
}
// 确定等式右边的值
a[0][n] = 1; a[n-1][n] = -1;
for(int i=1; i<n -1; i++) a[i][n] = 0;
// 这里给结点n的电势赋值为100
for(int i=0; i<=n; i++) a[n-1][i] = 0;
a[n-1][n-1] = 1; a[n-1][n] = 100;
//解方程
int free_num = gauss(a, n, n);
double ans = (x[n-1] - x[0]) / 1.0;
printf("Case #%d: %.2f\n", ++l, ans);
}
return 0;
}