Codeforces 267C 高斯消元解方程

来源:互联网 发布:成都国信安php 编辑:程序博客网 时间:2024/05/29 04:06

题目链接

首先,这个题还是蛮有意思的,,,

其次,一个sb的bug整了我一下午

题意:给出一个流量网络,告诉你每条边流量的上限,每个点(除了源点和汇点)都满足流量平衡,即流进 = 流出 ,还有一个关键的条件是对于任意的x y,从x走到y的流量和相等,流量和为从x到y每条边的流量相加(有正有负)。最后让你输出一种网络流的方案,使得总的流量最大


对于任意两个点,不管走哪条路径,流量和都是定值,这个有点类似于物理中的势能,从一个高度到达另一个高度,势能差不变,借此思路,可以设每个点的势能为x[i],那 边i j之间的流量就为x[j] - x[i],由每个点都满足流量守恒(除源汇外),可以列出n-2个方程来,举个例子,对于i这个点,枚举所有的邻接点j

x[i] - x[j1] + x[i] - x[j2] + x[j3] - x[i]  .... = 0 (要分 i->j  ,还是 j->i ,相应的系数就++ -- ) 

然后x1 和 xn随便设两个常数就好了,假设设为1 2 。

这样构造好方程解出来一组可行解,是忽略了每条边的流量限制的,现在,将每条边的流量限制放进去,可以算出每条边最大的容量

解是成比例的。


#include<cstdio>#include<cmath>#include<algorithm>using namespace std;#define _abs(x) ((x)>0?(x):-(x))#define REP(i,n) for(int i=0;i<n;i++) const int M = 5010;const int N = 110 ;int u[M] , v[M] , c[M];;int  fa[N] , f[N] ;int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}double a[N][N] , b[N] , x[N];void linear_equation(int n) //  sum(a[i][j] * x[j]) = b[i];{REP(i,n) {int p = i;for(int j = i; j < n; j++) if(_abs(a[j][i]) > _abs(a[p][i])) p = j;if(fabs(a[i][i]) < 1e-6) continue;//special judge,有些点可能不在点集中,会被0除if(p != i){ REP(j,n) swap(a[i][j],a[p][j]); swap(b[i],b[p]); }REP(j,n) if(j != i) {double con = - a[j][i] / a[i][i];for(int k = i; k < n; k++) a[j][k] += con * a[i][k];b[j] += con * b[i];}}REP(i,n) x[i] = b[i] / a[i][i];}int main(){int n , m;scanf("%d%d",&n,&m);REP(i,m) {scanf("%d%d%d",&u[i],&v[i],&c[i]); u[i] -- ; v[i] --;if(!f[u[i]]) f[u[i]]=1,fa[u[i]]=u[i];if(!f[v[i]]) f[v[i]]=1,fa[v[i]]=v[i];fa[find(u[i])] = find(v[i]);a[u[i]][v[i]]--,a[u[i]][u[i]]++;a[v[i]][u[i]]--,a[v[i]][v[i]]++;}if(!f[0] || !f[n-1] || find(0)!=find(n-1)) {REP(i,m+1) printf("0.000000000000000\n");return 0;}REP(i,n) a[0][i] = 0,a[n-1][i]=0;b[0] = 1; b[n-1] = 2;a[n-1][n-1] = 1; a[0][0]=1;linear_equation(n);double ing = 1e50;double tmp[M];REP(i,m)ing = min(ing,(double)c[i]/fabs(x[u[i]]-x[v[i]])); REP(i,n) x[i] *= ing;double ans = 0;REP(i,m) if(u[i]==0||v[i]==0) ans+=_abs(x[u[i]]-x[v[i]]);printf("%.10lf\n",ans);REP(i,m)  printf("%.10lf\n",x[v[i]]-x[u[i]]);return 0;}