HDU5006 Resistance(高斯消元)

给你一个复杂的网路图,然后告诉你s,t,求s,t的等效电阻。方法是设s的电势为1,t的电势为0.然后对于其它的每个点x,满足的是sigma(ux-uy)/R(x,y)(即对每个与x相连的节点y,电势差除以电阻的和为0,应该是基尔霍夫定律什么的),然后就列出来了一堆方程,解出每个点的电势,对于源点连出去的所有边,求一下电流,知道总电流,而且也知道总电势,就可以知道电阻了。

#include <iostream>

#include <cstdio>

#include <cstring>

#include <string>

#include <algorithm>

#include <cmath>

#include <queue>

#include <cassert>

#include <vector>

using namespace std;



#define maxn 11000

#define eps 1e-7

struct Edge{

    int u,v,c;

    Edge(int ui,int vi,int ci):u(ui),v(vi),c(ci){}

    Edge(){}

};

int dcmp(double x){

    return (x>eps)-(x<-eps);

}

vector<Edge> E;

vector<int> G[maxn];

int n,m,s,t;

int bel[maxn];

int btot;



void dfs(int u,int mark)

{

    bel[u]=mark;

    for(int i=0;i<G[u].size();++i){

        int v=G[u][i];

        if(bel[v]) continue;

        else dfs(v,mark);

    }

}



void getBelong()

{

    btot=0;

    memset(bel,0,sizeof(bel));

    for(int i=1;i<=n;++i){

        if(!bel[i]){

            ++btot;

            dfs(i,btot);

        }

    }

}



int cnt[500][500];

double mat[500][500];



void gauss(int n)

{

    for(int i=1;i<=n;++i){

        int pivot=i;

        for(int j=i;j<=n;++j){

            if(abs(mat[j][i])>abs(mat[pivot][i])) pivot=j;

        }

        for(int x=1;x<=n+1;++x){

            swap(mat[i][x],mat[pivot][x]);

        }

        if(abs(mat[i][i])<eps) continue;

        for(int j=i+1;j<=n+1;++j){

            mat[i][j]/=mat[i][i];

        }

        for(int j=1;j<=n;++j){

            if(i!=j){

                for(int k=i+1;k<=n+1;++k){

                    mat[j][k]-=mat[j][i]*mat[i][k];

                }

            }

        }

    }

}









int main()

{

    int T;cin>>T;

    while(T--){

        scanf("%d%d%d%d",&n,&m,&s,&t);

        for(int i=0;i<=n;++i) G[i].clear();

        E.clear();

        int ui,vi,ci;

        for(int i=0;i<m;++i){

            scanf("%d%d%d",&ui,&vi,&ci);

            if(ci==0){

                G[ui].push_back(vi);

                G[vi].push_back(ui);

            }

            else{

                E.push_back(Edge(ui,vi,ci));

            }

        }

        getBelong();

        if(bel[s]==bel[t]){

            printf("%.6lf\n",0);continue;

        }

        memset(cnt,0,sizeof(cnt));

        memset(mat,0,sizeof(mat));

        for(int i=0;i<E.size();++i){

            ui=E[i].u;vi=E[i].v;

            if(bel[ui]!=bel[vi]){

                cnt[bel[ui]][bel[vi]]++;

                cnt[bel[vi]][bel[ui]]++;

            }

        }

        for(int i=1;i<=btot;++i){

            if(i==bel[s]){

                mat[i][i]=1.0;

                mat[i][btot+1]=1;

                continue;

            }

            else if(i==bel[t]){

                mat[i][i]=1.0;

                mat[i][btot+1]=0;

                continue;

            }

            for(int j=1;j<=btot;++j){

                if(i==j||cnt[i][j]==0) continue;

                mat[i][i]+=cnt[i][j];

                mat[i][j]-=cnt[i][j];

            }

        }

        gauss(btot);

        double I=0;

        for(int i=1;i<=btot;++i){

            if(i==bel[s]) continue;

            if(cnt[bel[s]][i]>0){

                I+=(1-mat[i][btot+1])*cnt[bel[s]][i];

            }

        }

        double R=1/I;

        if(dcmp(I-eps)==0) {

            printf("inf\n");

            continue;

        }

        printf("%.6lf\n",R);

    }

    return 0;

}

 

你可能感兴趣的:(HDU)