Cod sursa(job #109765)

Utilizator stef2nStefan Istrate stef2n Data 25 noiembrie 2007 12:39:48
Problema Tunelul groazei Scor 100
Compilator cpp Status done
Runda preONI 2008, Runda 1, Clasele 11-12 Marime 3.04 kb
/*
 *  Complexitate: O(N^3)
 */

//#define DEBUG

#include <cstdio>
#include <cmath>
#include <cstdlib>
#ifdef DEBUG
#include <iostream>
#endif
using namespace std;

#define NMAX 256

int N, M;
int mch[NMAX][NMAX];
int grad[NMAX];
double cost[NMAX][NMAX];
double P[NMAX], A[NMAX][NMAX], B[NMAX];
double AVG[NMAX];

void read_data()
{
    int u, v, c;
    scanf("%d %d",&N,&M);
    for(int i=0; i<M; ++i)
    {
        scanf("%d %d %d",&u,&v,&c);
        mch[u][v]++;
        mch[v][u]++;
        grad[u]++;
        grad[v]++;
        cost[u][v]+=c;
        cost[v][u]+=c;
    }
    for(int i=1; i<=N; ++i)
        for(int j=1; j<=N; ++j)
            if(mch[i][j])
                cost[i][j]/=(double)mch[i][j];
}

void init1()
{
    A[1][1]=1.;
    for(int i=2; i<=N; ++i)
        A[1][i]=0.;
    B[1]=1.;
    for(int i=2; i<=N; ++i)
    {
        for(int j=1; j<=N; ++j)
            if(i==j)
                A[i][j]=-1.;
            else
                if(j==N)
                    A[i][j]=0.;
                else
                    A[i][j]=(double)mch[i][j]/(double)grad[j];
        B[i]=0.;
    }
#ifdef DEBUG
    for(int i=1; i<=N; ++i)
    {
        for(int j=1; j<=N; ++j)
            cerr<<A[i][j]<<" ";
        cerr<<" = "<<B[i]<<endl;
    }
    cerr<<endl;
#endif
}

void init2()
{
    for(int i=1; i<=N; ++i)
    {
        B[i]=0.;
        for(int j=1; j<=N; ++j)
            if(i==j)
                A[i][j]=-1.;
            else
                if(j==N)
                    A[i][j]=0.;
                else
                {
                    double p=P[j]*(double)mch[i][j]/(double)grad[j];
                    A[i][j]=p/P[i];
                    B[i]-=p*cost[i][j]/P[i];
                }
    }
#ifdef DEBUG
    for(int i=1; i<=N; ++i)
    {
        for(int j=1; j<=N; ++j)
            cerr<<A[i][j]<<" ";
        cerr<<" = "<<B[i]<<endl;
    }
    cerr<<endl;
#endif
}

int find(int i)
{
    int p=i; double coef=0.;
    for(int j=i; j<=N; ++j)
        if(coef<fabs(A[j][i]))
        {
            coef=fabs(A[j][i]);
            p=j;
        }
    return p;
}

void replace(int i)
{
    for(int j=i+1; j<=N; ++j)
    {
        double aux=A[j][i];
        B[j]-=aux*B[i];
        for(int k=i; k<=N; ++k)
            A[j][k]-=aux*A[i][k];
    }
}

void Gauss(double (&P)[NMAX])
{
    int k; double aux;
    for(int i=1; i<=N; ++i)
    {
        k=find(i);
        for(int j=i; j<=N; ++j)
        {
            aux=A[i][j];
            A[i][j]=A[k][j];
            A[k][j]=aux;
        }
        aux=B[i];
        B[i]=B[k];
        B[k]=aux;
        aux=A[i][i];
        B[i]/=aux;
        for(int j=i; j<=N; ++j)
            A[i][j]/=aux;
        replace(i);
    }
    for(int i=N; i>=1; --i)
    {
        P[i]=B[i];
        for(int j=i+1; j<=N; ++j)
            P[i]-=A[i][j]*P[j];
    }
#ifdef DEBUG
    for(int i=1; i<=N; ++i)
        cerr<<P[i]<<" ";
    cerr<<endl<<endl;
#endif
}


int main()
{
    freopen("tunel.in","r",stdin);
    freopen("tunel.out","w",stdout);
    read_data();
    init1();
    Gauss(P);
    init2();
    Gauss(AVG);
    printf("%lf\n",AVG[N]);
    return 0;
}