Rational Resistors
Time Limit: 15 seconds
"Resistance will be punished. Cooperation will be rewarded." |
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 rspecifying 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 Input | Sample 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("");
}
}