uva 10808 - Rational Resistors

来源:互联网 发布:ubuntu忘记登录密码 编辑:程序博客网 时间:2024/05/21 08:46

uva  10808 - Rational Resistors

题意:给出一个纯电阻网络,求任意两点间的等效电阻 , 输出分数形式。

看似简单的电路题用程序实现起来却非常棘手,首先得自己定义分数的各种运算,有不确long long 的精度是否够用。。

思路很简单,一个比较简单的方法是采用节点电压法(参见http://baike.baidu.com/link?url=tsPt2fO-B8N57v2A1LHvgaRkliFfSKUcEtZnTBxACzimkTYJTOaCY4IjKcOTds0TRenmLEyZAXCeJDIfP17Onq)

在待求两点间接一个1安培的电流源,根据节点电压法列方程组,解出两点间电压的差值在数值上等于两点间的等效电阻。

这题不太容易确定long long是否够用,如果要手写高精度分数,简直奔溃。。 还好在uva的讨论版上看到有人用long long 通过了。(写的不好依然会超出long long)

参考代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <cmath>#include <cstdlib>#include <map>#include <vector>#include <queue>#include <set>using namespace std;typedef long long LL;const int maxn = 20;//关于分数的一些定义,有些用没用到----------------struct Frac{    LL a,b;    friend ostream& operator << (ostream & ,Frac &) ;    friend istream& operator >> (istream & ,Frac &) ;    friend Frac operator + (const Frac & , const Frac &);    friend Frac operator - (const Frac & , const Frac &);    friend Frac operator * (const Frac & , const Frac &);    friend Frac operator / (const Frac & , const Frac &);    void operator += (const Frac &f) {*this = *this + f ;}    void operator -= (const Frac &f) {*this = *this - f ;}    void operator *= (const Frac &f) {*this = *this * f ;}    void operator /= (const Frac &f) {*this = *this / f ;}    void init_zero(){a=0 ,b=1;}    LL gcd(LL x,LL y){ return y==0 ? x : gcd(y , x%y); };    inline void simplify(){        LL r = gcd(a,b);        if(r!=0) a /= r ,b/=r;    }    Frac(LL x=0,LL y=1) : a(x) , b(y) {simplify(); }    bool isInf()const { return a!=0 && b==0 ; }    bool isZero()const { return a==0 && b!=0 ;}};Frac operator + (const Frac & f1,const Frac &f2){    return Frac(f1.a*f2.b + f2.a*f1.b , f1.b*f2.b);}Frac operator - (const Frac & f1,const Frac &f2){    return Frac(f1.a*f2.b - f2.a*f1.b , f1.b*f2.b);}Frac operator * (const Frac & f1,const Frac &f2){    return Frac(f1.a*f2.a ,f1.b*f2.b);}Frac operator / (const Frac & f1,const Frac &f2){    return Frac(f1.a*f2.b , f1.b*f2.a);}ostream & operator << (ostream & out ,Frac & c){    c.simplify();    out<<abs(c.a)<<"/"<<abs(c.b); // 注意要输出绝对值    return out;}istream & operator >> (istream & in , Frac & c){    in>>c.a>>c.b;    return in;}//---------------------分数定义结束--------------------------typedef Frac Mat[maxn][maxn];Mat A;Frac gauss(Mat A,int n,int u,int v){    if(u==v) return 0;    int i,j,k,r;    for(i=0;i<n;i++){        for(r=i;r<n;r++) if(A[r][i].a != 0) break;        if(r >= n) continue;        if(r!=i) for(int j=0;j<=n;j++) swap(A[i][j] , A[r][j]);        /* 这么写会超精度          for(k=0 ; k<n ;k++) if(k!=i && !A[k][i].isZero()) {            Frac f = A[k][i] / A[i][i];            for(j=n ; j>i ;j--) A[k][j] -=  f * A[i][j];            A[k][i] = 0;        }        */        for(j = n ; j>i ;j--) A[i][j] /= A[i][i];        A[i][i] = 1;        for(k=0 ; k<n ;k++) if(k!=i && !A[k][i].isZero()) {            for(j=n ; j>i ;j--) A[k][j] -=  A[k][i]* A[i][j];            A[k][i] = 0;        }    }    return A[u][n]/A[u][u] - A[v][n]/A[v][v];}Frac conduct[maxn][maxn]; // 电导int fa[maxn];void fa_init(){    for(int i=0;i<maxn;i++) fa[i] = i;}int Find(int x){    return fa[x]==x ? x : fa[x] = Find(fa[x]);}void union_fa(int x,int y){    int fx = Find(x)  , fy = Find(y);    if(fx != fy) fa[fx] = fy;}Frac solve(int n , int u , int v){    int tn = 0 , id[20] , tu , tv;    for(int i=0 ; i<n ;i++) {        if(i==u) tu = tn;        if(i==v) tv = tn;        if(Find(i) == Find(u)) id[tn++] = i;// 与u,v不连通的点没写进方程组。    }    tn++;    for(int i=0;i<tn;i++) for(int j=0;j<=tn;j++) A[i][j].init_zero();    for(int i=0;i<tn-1;i++){         for(int j=0;j<tn-1;j++){            if(i==j) continue;            A[i][i] += conduct[id[i]][id[j]]; // 自导之和            A[i][j] -= conduct[id[i]][id[j]]; // 互导之和         }    }    A[tu][tn] = 1; //1安培的电流源    A[tv][tn] = -1;    A[tn-1][0] = 1;//接地点电压为零,方程即为 1*V = 0    return gauss(A,tn,tu,tv);}int main(){    //freopen("input.txt","r",stdin);    ios::sync_with_stdio(0);    int T , cas = 1;    cin>>T;    while(T--){        fa_init();        int n,m;        cin>>n>>m;        for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) conduct[i][j].init_zero();        int u,v,r;        while(m--){            cin>>u>>v>>r;            if(u==v) continue;            union_fa(u,v);            conduct[u][v] += (Frac){1,r};            conduct[v][u] += (Frac){1,r};        }        int Q;        cout<<"Case #"<<cas++<<":"<<endl;        cin>>Q;        while(Q--){            cin>>u>>v;            Frac ans;            if(Find(u) != Find(v)) ans = (Frac){1 , 0};  // 若不连通,电阻为无穷大。            else if(u==v)          ans = 0;            else                   ans = solve(n , u , v);            cout<<"Resistance between "<<u<<" and "<<v<<" is "<<ans<<endl;        }        cout<<endl;    }    return 0;}


0 0