Description
你突破了无数艰难险阻,终于解决了上面那道题,众神犇瞬间就震惊了。他们发现居然有人可以把那种非人类做的题目做出来。他们一致同意,最后这道题不能再出数学题了。考虑到两位小盆友的状态,他们决定考考你的初中物理水平。 一个电路板,有 N 个接点,M 个电阻。电阻两端都在接点上,两位小盆友很聪明,他们拿出了一个欧姆表,瞬间就虐爆了…不过你也不甘落后,你肯定不会用这种投机取巧、误差巨大的方法,于是你看向了你的电脑。
Input
多组数据,输入直到文件结束
每组数据第一行两个整数N,M
接下来 M 行,每行三个非负整数 X,Y,R,表示电阻连接的两
接点和阻值。
Output
每组数据输出一行,一个实数,四舍五入到小数点后两位
Sample Input
2 1
1 2 1
Sample Output
1.00
Hint
0<N≤200
0<M≤50000
Solution
这题BZOJ居然没给数据范围!狂WA了若干次都没发现原因,坑得要命TAT
根据我们的物理知识
Iab=UR=ϕ(b)−ϕ(a)Rab
,我们又知道对于**(除起始点外
)任意一个点流入的电流等于流出的电流**,于是我们可以令第一个点流出电流
I1=1
,则最后一点流入电流
IN=1
,再令第N个点电势
ϕ(N)=0
,求出的
ϕ(1)
即为要求的等效电阻.第一个点的值为-1,最后一个点的值为1
Code
#include<bits/stdc++.h>
#define maxm 100010
#define maxn 1010
#define eps 1e-6
// #define DEBUG
using namespace std;
int n,m,num_edge;
double a[maxn][maxn];
int now[maxm],pre[maxm],to[maxm],deg[maxm],w[maxm];
int dcmp(double x)
{
if(abs(x)<=eps) return 0;
else return x>0?1:-1;
}
void add_edge(int u,int v,int wi)
{
pre[++num_edge]=now[u];
w[num_edge]=wi;
now[u]=num_edge;
to[num_edge]=v;
deg[v]++;
}
inline int read()
{
char ch;
int sign=1,read=0;
do
ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-');
if(ch=='-') sign=-1,ch=getchar();
while(ch>='0' && ch<='9')
{
read=read*10+ch-'0';
ch=getchar();
}
return sign*read;
}
void init()
{
num_edge=0;
memset(a,0,sizeof(a));
for(int i=1;i<=max(n,m);++i)
deg[i]=pre[i]=now[i]=to[i]=w[i]=0;
for(int i=1,x,y,r;i<=m;++i)
x=read(),y=read(),r=read(),add_edge(x,y,r),add_edge(y,x,r);
for(int i=1;i<=n;++i)
for(int x=now[i];x;x=pre[x])
{
a[i][to[x]]+=1.0/w[x];
a[i][i]-=1.0/w[x];
}
a[1][n+1]=-1.0;
a[n][n+1]=1.0;
a[n][n]-=1.0;
}
void gauss()
{
for(int i=1;i<=n;++i)
{
if(!dcmp(a[i][i]))
{
int k=i;
while(!dcmp(a[k][k])) k++;
swap(a[i],a[k]);
}
for(int j=i+1;j<=n;++j)
{
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;
}
}
for(int i=n;i>1;--i)
for(int j=1;j<i;++j)
{
a[j][n+1]-=a[i][n+1]*(a[j][i]/a[i][i]);
a[j][i]=0;
}
printf("%.2lf\n",a[1][n+1]/a[1][1]+eps);
}
int main()
{
#ifdef DEBUG
freopen("resistor.in","r",stdin);
/*#else
freopen("resistor.in","r",stdin);
freopen("resistor.out","w",stdout);*/
#endif
while(scanf("%d%d",&n,&m)==2)
{
init();
#ifdef DEBUG
for(int i=1;i<=n;++i)
{
cerr<<"i="<<i<<" -->";
for(int p=now[i];p;p=pre[p])
cerr<<to[p]<<" ";
cerr<<";"<<endl;
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n+1;++j)
printf("%.3lf ",a[i][j]);
cout<<endl;}
#endif
gauss();
}
return 0;
}