Electric resistance (高斯消元)

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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值