Electric resistance

一、题目

点此看题
题目描述
给定 n n 个点, m m 条线,每条连接 ( u , v ) (u,v) 的线有一个阻值为 c c 的电阻,求出这个电路的等效电阻。
数据范围
多组数据, 1 T 100 , 1 < n 50 , 1 m 2000 , 1 c 2000 1\leq T\leq 100,1<n\leq 50,1\leq m\leq 2000,1\leq c\leq 2000

二、解法

可以考虑把这个局部电路接上电源( 1000 V 1000V ),然后求出电流,欧姆定律算电阻。

考虑 n 2 n-2 个未知数表示每个点的电压,我们已知 U 1 = 1000 V U_1=1000V , U n = 0 V U_n=0V ,其他的电压满足下式:
U i U j R i , j = 0 \sum \frac{U_i-U_j}{R_{i,j}}=0 R i , j R_{i,j} 需要给定,否则该项不存在,这个式子就是说明了一个点流入的电流等于流出的电流,然后高斯消元即可。

#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);
	}
}
发布了192 篇原创文章 · 获赞 12 · 访问量 3348

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/103823082