http://www.lydsy.com/JudgeOnline/problem.php?id=2419
题意:
n个点m个电阻构成一张图,求1到n的等效电阻
第一节课看一道题弃疗,于是来做这道物理题
orz PoPoQQQ大爷 http://blog.csdn.net/popoqqq/article/details/41703037
电流形成的图类似一个流网络,也满足流量平衡:(貌似好像有个叫基尔霍夫定律的玩意儿,然而我只知道基尔霍夫矩阵....)
令从$1$到$n$流的电流$I=1$,则:
$\sum\limits\frac{U_i-U_j}{R_{i,j}}=0$
$\sum\limits\frac{U_1-U_j}{R_{1,j}}=1$
$\sum\limits\frac{U_n-U_j}{R_{i,n}}=-1$
$U_n=0$
辣么答案就是$U_1$啦
一个点一个方程,然后高斯消元
怎么让$U_n=0$呢?这可是方程啊.............直接赋值就行了
实现上的小技巧:两点之间可能有多个电阻,所以直接保存电阻的倒数(电导)就好了,直接相加
我这个xx竟然忘记输出后换行了...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N=505; int n,m,u,v; double g[N][N],a[N][N],r; void buildEquation(){ for(int i=1;i<n;i++) for(int j=1;j<=n;j++) a[i][i]+=g[i][j],a[i][j]-=g[i][j]; a[1][n+1]=1; a[n][n+1]=-1; a[n][n]=1;a[n][n+1]=0; } void GaussElimination(){ for(int i=1;i<=n;i++){ int r=i; for(int j=i+1;j<=n;j++) if(abs(a[j][i])>abs(a[r][i])) r=j; if(r!=i) for(int k=1;k<=n+1;k++) swap(a[i][k],a[r][k]); for(int j=i+1;j<=n;j++){ double t=a[j][i]/a[i][i]; for(int k=i;k<=n+1;k++) a[j][k]-=a[i][k]*t; } } for(int i=n;i>=1;i--){ for(int j=n;j>i;j--) a[i][n+1]-=a[j][n+1]*a[i][j]; a[i][n+1]/=a[i][i]; } } void ini(){memset(g,0,sizeof(g));memset(a,0,sizeof(a));} int main(){ freopen("in","r",stdin); while(scanf("%d%d",&n,&m)!=EOF){ ini(); for(int i=1;i<=m;i++){ scanf("%d%d%lf",&u,&v,&r); if(u==v) continue; g[u][v]+=1/r;g[v][u]+=1/r; } buildEquation(); GaussElimination(); printf("%.2lf\n",a[1][n+1]); } }