Listing Electro.CPP
#include <fstream.h>
#include <stdlib.h>
#define Nmax 101
#define Lmax 101
double R[Lmax],E[Lmax],I[Lmax];
int va[Lmax],vb[Lmax],le[Lmax];
int m[Nmax],c[Nmax],ms[Nmax];
double *a[Lmax],b;
int N,L,i,j,k,ns,t,ne;
void Citeste()
{
ifstream is("elth.in", ios::in);
is>>N>>L;
for(i=1;i<=L;i++)
is>>va[i]>>vb[i]>>R[i]>>E[i]>>le[i];
is.Close();
}
int find(int k,int p)
// Gaseste un drum in arbore intre k si t
// (t global). Daca nu exista drum intoarce 0
// p = nodul precedent, pentru a evita
// intoarcerea pe aceeasi muchie
{
int l,i;
if (k==t) return 1;
for(i=1;i<N;i++)
if (va[l=ms[i]] == k && vb[l] != p)
if (find(vb[l],k)) //Gasit
{
a[ne][l]+=R[l];
//Adaug termenul R[l]*I[l]
a[ne][le[l]]-=E[l];
//Adaug termenul -E[l] la termenul liber,
//respectiv termenul -E[l]*I[le[l]]
return 1;
} else;
else
if (vb[l]==k && va[l]!=p)
if (find(va[l],k))
{
a[ne][l]-=R[l]; a[ne][le[l]]+=E[l];
return 1;
}
return 0;
};
void Sistemul()
// Construieste sistemul de ecuatii Kirchhoff
{
for (i=1; i<=L; i++)
{
if (!(a[i] = New double[L+1]))
{
cerr << "Memorie insuficienta!";
exit(1);
};
memset(a[i], 0, (L+1) * Sizeof(double));
}
//K1 : Primele N-1 ecuatii: latura i iese
//din va[i] si intra in vb[i]
for (i=1; i<=L; i++)
{ a[va[i]][i]=1; a[vb[i]][i]=-1;
}
memset(a[N],0,(L+1)*Sizeof(double));
//Ultima nu mai conteaza
for(i=1;i<=N;i++) c[i]=i;
//Arborele partial: Kruskal neoptimizat (100 max.)
for (i=1;i<=L;i++)
if (c[va[i]]!=c[vb[i]])
{
ms[++ns]=i;
// ns:numarul de muchii selectate;
// ms: muchiile sel.
k=c[vb[i]];
for (j=1;j<=N;j++)
if (c[j]==k) c[j]=c[va[i]];
if (ns==N-1) break;
};
// K2
ns = 1; ne = N; //ne = Ecuatia curenta
for (i=1;i<=L;i++)
if (i==ms[ns]) ns++;
// Sarim peste muchiile din arbore
else
{
//Gasesc un ciclu
t=vb[i]; // t = "tinta"
find(va[i],0);
a[ne][i]-=R[i];
//Adaug latura i, insa in sens invers
a[ne][le[i]]+=E[i]; ne++;
}
}
void Rezolva()
{
memset(c, 0, Sizeof(c)); //"Reciclez" c
// Gauss
for(i=1;i<=L;i++)
{
for(j=1;j<=L;j++)
if (a[i][j]) {t=j; j=L;}
//t exista intotdeauna
c[t]=i;
//I[t] este det. de ecuatia cu numarul i
for (j=1; j<=L; j++)
//Reduc celelalte ecuatii
if (j!=i)
{
b=-a[j][t]/a[i][t];
for(k=0;k<=L;k++)
a[j][k]+=b*a[i][k];
//se observa ca elementul a[j][t] a devenit 0
}
}
for(i=1;i<=L;i++)
I[i]=-a[c[i]][0]/a[c[i]][i];
}
void Scrie()
{
ofstream os("elth.out");
os.precision(2);
for(i=1;i<=L;i++) os<<I[i]<<"\n";
os.Close();
}
void main()
{
Citeste();
Sistemul();
Rezolva();
Scrie();
}