一、题目
点此看题
题目描述
给定
个点,
条线,每条连接
的线有一个阻值为
的电阻,求出这个电路的等效电阻。
数据范围
多组数据,
二、解法
可以考虑把这个局部电路接上电源( ),然后求出电流,欧姆定律算电阻。
考虑
个未知数表示每个点的电压,我们已知
,
,其他的电压满足下式:
需要给定,否则该项不存在,这个式子就是说明了一个点流入的电流等于流出的电流,然后高斯消元即可。
#include <cstdio>
#include <vector>
#include <iostream>
#define eps 1e-7
#define db double
const int M = 105;
using namespace std;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int T,n,m;db ans,a[M][M],b[M];
vector<pair<int,int> > g;
int cmp(db x,db y)
{
if(x-y>eps) return 1;
if(x-y<-eps) return -1;
return 0;
}
bool gauss(int n,db a[][M])
{
bool flag=1;
for(int i=1;i<=n;i++)
{
int Max=i;
for(int r=i+1;r<=n;r++)
if(cmp(a[Max][i],a[r][i])==-1)
Max=r;
swap(a[i],a[Max]);
if(cmp(a[i][i],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 get(int n,db a[][M],db *b)
{
if(!gauss(n,a))
{
for(int i=1;i<=n;i++)
{
bool flag=1;
for(int j=1;j<=n;j++)
if(cmp(a[i][j],0)!=0)
flag=0;
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;
}
int main()
{
T=read();
int Cases=0;
while(T--)
{
ans=0;
n=read();m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
a[i][j]=0;
g.clear();
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),c=read();
if(u==1) g.push_back(make_pair(v,c));
if(v==1) g.push_back(make_pair(u,c));
if(u!=1 && u!=n) a[u][u]+=1.0/c,a[u][v]-=1.0/c;
if(v!=1 && v!=n) a[v][v]+=1.0/c,a[v][u]-=1.0/c;
}
a[1][1]=1;a[n][n]=1;
a[1][n+1]=1000;
get(n,a,b);
for(int i=0;i<g.size();i++)
ans+=(b[1]-b[g[i].first])/g[i].second;
printf("Case #%d: %.2lf\n",++Cases,b[1]/ans);
}
}