UVA 10808 - Rational Resistors 高斯消元

本文深入探讨了信息技术领域的核心概念与应用实例,涵盖了从基础编程到高级人工智能的广泛主题,包括但不限于前端开发、后端开发、移动开发、游戏开发、大数据开发、AI音视频处理、测试、基础运维等关键领域。文章不仅介绍了各领域的基本原理和技术细节,还通过实际案例展示了这些技术在现代应用中的实践与创新。

Problem ?
Rational Resistors
Time Limit: 15 seconds

"Resistance will be punished.
Cooperation will be rewarded."
J. Michael Straczynski, "Babylon 5" and "Jeremiah".

Given a network of resistors, what is the equivalent resistance betweentwo given points in the network? More precisely, consider an undirected,weighted graph, where each edge is a wire with the edge weightrepresenting its resistance, in Ohms. Given a pair of nodes, A and B, in thisgraph, imagine passing 1 Ampere of current from A to B. What will be thevoltage between A and B, in Volts?

A brief review of high school physics. For any pair of points, P and Q, in thenetwork, the voltage between the points is the difference in potentials at thetwo points (V(P) - V(Q)) and is equal to the current from P to Q times theresistance between P and Q. For any point in the network, the sum of thecurrents entering the point is zero (conservation of charge).

Warning! This problem is harder than it seems.

Input
The first line of input gives the number of cases, N (N<30).N test cases follow. Each one starts with a description of a graph:

n m (the number of nodes and wires in the graph)
n will not be larger than 16. The next m lines contain 3 integerseach:
u v r
specifying that there is a wire with resistance r (0<r<10)connecting node u to node v. The nodes are numbered from 0 ton-1. There can be multiple wires connecting the same pairof nodes and wires connecting a node to itself.The next line of each test case will contain the number of queries, Q(0<=Q<=10). The next Q lines will list pairs of nodesA and B.

Output
For each test case, output the line "Case #x:", where x is thenumber of the test case. Then print Q lines of the form"Resistance between A and B is s/t.", where s/tis a fraction in lowest terms. Print "1/0" if no current can go from Ato B. Finally, print an empty line after each test case.

Sample InputSample Output
4
3 2
0 1 1
1 2 2
2
0 2
1 0
2 2
0 1 1
1 0 2
1
0 1
2 0
1
0 1
4 4
0 1 1
1 2 2
2 3 3
1 3 1
1
0 3
Case #1:
Resistance between 0 and 2 is 3/1
Resistance between 1 and 0 is 1/1

Case #2:
Resistance between 0 and 1 is 2/3

Case #3:
Resistance between 0 and 1 is 1/0

Case #4:
Resistance between 0 and 3 is 11/6


Problemsetter: Igor Naverniouk


题意:给出一个电路图和电阻,电流为1A,问从S到T的等效电阻。


思路:直接把每个节点的电势设成未知数,然后列出方程组进行高斯消元就行了。只不过要用分数进行运算而已。具体直接看代码就行了。


代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <math.h>
using namespace std;
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,x,sizeof(a))
#define eb emplace_back
#define ll long long
const int maxn = 30 + 5;
struct Fact
{
    ll a,b;
    Fact(ll a = 0,ll b = 1)
    :a(a), b(b) {
        sim();
    }
    void sim()
    {
        if (b < 0) b = -b, a = -a;
        ll g = abs(__gcd(a,b));
        if (g > 1) a /= g, b /= g;
    }
    Fact operator + (const Fact & f) const
    {
        return Fact(a * f.b + f.a * b, b * f.b);
    }
    Fact operator - (const Fact & f) const
    {
        return Fact(a * f.b - f.a * b, f.b * b);
    }
    Fact operator * (const Fact & f) const
    {
        return Fact(a * f.a, b * f.b);
    }
    Fact operator / (const Fact & f) const
    {
        return Fact(a * f.b, f.a * b);
    }
    void print() const
    {
        printf("%3d/%-3d",a,b);
    }
};


Fact M[maxn][maxn];

int p[maxn];
inline int find(int x)
{
    return p[x] == x ? x : p[x] = find(p[x]);
}

pair<int,pair<int,int> > edges[maxn*maxn];

int n,m;
void input()
{
   scanf("%d%d",&n,&m);
   rep(i,0,n) p[i] = i;
   rep(i,0,m) {
       int u,v,w;
       scanf("%d%d%d",&u,&v,&w);
       edges[i].first = u;
       edges[i].second.first = v;
       edges[i].second.second = w;
       u = find(u), v = find(v);
       if (u != v) p[u] = v;
   }
}


void build()
{
    rep(i,0,m) {
        int u,v,r;
        u = edges[i].first;
        v = edges[i].second.first;
        r = edges[i].second.second;
        if (u == v) continue;
        M[u][v] = M[u][v] + Fact(1, r);
        M[u][u] = M[u][u] - Fact(1, r);

        swap(u,v);
        M[u][v] = M[u][v] + Fact(1, r);
        M[u][u] = M[u][u] - Fact(1, r);
    }
}

void out(int n,int m)
{
    puts("");
    rep(i,0,n) {
        rep(j,0,m) M[i][j].print();
        puts("");
    }
    puts("");
}

void gauss(int n,int m)
{
    int i,j,k;
    for(i = 0; i < n; ++i) {
        for(k = i; k < n; ++k)
        if (M[k][i].a) break;
        if (k == n) break;
        if (k != i) {
            for(j = i; j < m; ++j)
                swap(M[i][j],M[k][j]);
        }
        for(j = i+1; j < m; ++j)
            M[i][j] = M[i][j] / M[i][i];
        M[i][i] = Fact(1);
        for(k = 0; k < n; ++k) if (M[k][i].a && i != k) {
            Fact f = M[k][i] / M[i][i];
            for(j = i; j < m; ++j) if (M[i][j].a)
                M[k][j] = M[k][j] - f * M[i][j];
        }

       // out(n,m);
    }
}

void solve()
{
    int Q; scanf("%d",&Q);
    rep(i,0,maxn) rep(j,0,maxn) M[i][j] = Fact();
    build();
    vector<pair<int,int> > qry;
    rep(i,0,Q) {
        int s, t; scanf("%d%d",&s,&t);
        qry.push_back({s,t});
        M[s][i+n] = Fact(1);
        M[t][i+n] = Fact(-1);
    }
    M[n][0] = Fact(1);
   // out(n+1,n+Q);
    gauss(n+1,n+Q);
    //out(n+1,n+Q);
    rep(i,0,Q) {
        int s,t;
        s = qry[i].first; t = qry[i].second;
        printf("Resistance between %d and %d is ",s,t);
        if (find(s) != find(t)) puts("1/0");
        else {
            Fact U = M[t][n+i] - M[s][n+i];
            printf("%d/%d\n",U.a,U.b);
        }
    }
}


int main()
{
    //Getinput(); return 0;
    #ifdef ACM
        freopen("in.txt","r",stdin);
      //  freopen("out.txt","w",stdout);
    #endif // ACM
    int T; cin >> T;
    rep(cas,1,T+1) {
        input();
        printf("Case #%d:\n",cas);
        solve();
        puts("");
    }
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值