/*题目大意:有N条排水管道连接编号为1~N个的节点,从Si到Ei的排水管道的最大容量是Ci。输入第一行N , M ,接着又N行,分别是每条排水管道的Si,Ei,Ci。求:从节点1到节点M最大能够通过的流量是多少。*/
/*这是一道很明显的最大流问题,可以用网络流算法来稿,还可以用线性规划来做。我用线性规划来搞的。*/
/*节点的流入流出以及管道的最大容量为约束条件,每条水管通过的流量为变量*/
/*
设Xi表示第i条水管的实际流量,设节点 j 有Xj1 ~ Xjp 流入,Xk1 ~ Xkq 流出(1<j<M;{ Xj1 , Xj2 , Xj3 .....Xjp }属于 X , { Xk1 , Xk2 , Xk3 .....Xkp }属于 X)
可以构造下列的约束方程组:
Xi < =Ci ; ----------------------------------------------------------------------------------------------------------------(1 < = i < = N)
( Xj1 + Xj2 + . . . + Xjp ) - ( Xk1 + Xk2 + . . . + Xkp ) < = 0 ; ---------------------------------------------------------(1 < j < M)
( Xk1 + Xk2 + . . . + Xkp ) - ( Xj1 + Xj2 + . . . + Xjp ) < = 0 ; ---------------------------------------------------------(1 < j < M)
( X11 + X12 + . . . + X1p ) - ( Xm1 + Xm2 + . . . + Xmp ) < = 0 ;
( Xm1 + Xm2 + . . . + Xmp ) - ( X11 + X12 + . . . + X1p ) < = 0 ;
目标函数:C=Xm1+Xm2+...+Xmp;
(注意:对于开始节点1和结束节点N,如果有直接连接的话,( X11 + X12 + . . . + X1p )和( Xm1 + Xm2 + . . . + Xmp )中有重复的元素,也就是说,做减法之后,某一个或几个Xi的系数就是0,所以转换的时候要注意!!!)
Source Code
Problem: 1273 | User: imutzcy | |
Memory: 1184K | Time: 63MS | |
Language: C++ | Result: Accepted |
- Source Code
#include<functional> #include<algorithm> #include<iostream> #include<fstream> #include<sstream> #include<iomanip> #include<numeric> #include<cstring> #include<cassert> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<stack> #include<cmath> #include<ctime> #include<list> #include<set> #include<map> using namespace std; /*const int r=2;//原线性规划问题中的变量个数,即:松弛变量前的变量个数 */ int r; /*const int m=3;//先行约束条件个数 */ int m; const double eps=1e-6; /*const double Max=1<<30;*/ const double Max=1e10; /*double matrix[m+2][r+2];//d单纯性算法的表格 */ double matrix[610][210]; int flag; /* flag = = 0 , 表示目标函数的最大值无边界,一般认为无解; flag = = 1, 表示有唯一的最优基本可行解 flag = = 2, 表示目标函数值确定,但最优的基本可行解不唯一 */ int main() { int N,M,from,to,flow; while(~scanf("%d%d",&N,&M)){ //N边,有N个变量;M顶点,有2M+N个约束; r=N; m=2*M+N; memset(matrix,0,sizeof(matrix)); for(int i=1;i<=N;i++){ scanf("%d%d%d",&from,&to,&flow); //边的流量小于最大容量 matrix[2*M+i][i]=1; matrix[2*M+i][r+1]=flow; //流入等于流出,用 < =和 > = 表示等于... 注释(1) if(from!=1){ matrix[from*2-1][i]=-1; matrix[from*2][i]=1;; } else if(to!=M){ //注意特殊的开始节点和结束节点,是所有从开始流出的等于从结束流入的 //这里用第 2 * M 和 2 * M - 1 个约束表示这种关系 //同时,要注意的是,直接从开始到结束点的边要除外,否则会造成标记错误...注释(2) matrix[2*M][i]=1; matrix[2*M-1][i]=-1; } //同注释(1) if(to!=M){ matrix[to*2][i]=-1; matrix[to*2-1][i]=1; } else{ if(from!=1){ //同注释(2) matrix[2*M][i]=-1; matrix[2*M-1][i]=1; } //目标函数,C=Xa+Xb+Xc+...+Xz , Xa+Xb+Xc+..+Xz为所有连向结束节点的边,求MAX(C) matrix[m+1][i]=-1; } matrix[0][i]=i;//标记边的序号,最后可以输出解的细节 } /* //松弛变量,初始一个基本可行解之后的表格 for(int i=1;i<=m+1;i++) for(int j=1;j<=r+1;j++) scanf("%lf",&matrix[i][j]); */ while(1){ flag=1; //寻找非基本变量 int ru; for(ru=1;ru<=r+1;ru++) if(matrix[m+1][ru]<0) break; //若找不到合适的非基本变量,说明目标函数已最优 if(ru>r+1) break; /* if(ru>r+1){ //判断最优基本可行解是否唯一 for(ru=1;ru<=r+1;ru++){ if(matrix[m+1][ru]<eps&&matrix[m+1][ru]>-eps){ flag=2; break; } } break; } */ double Min=Max; //寻找基本变量 int chu; for(int j=1;j<=m;j++){ if(matrix[j][ru]>0){ double tmp=matrix[j][r+1]/matrix[j][ru]; if(tmp<Min){ Min=tmp; chu=j; } } } /* //如果找不到合适的基本变量,说明目标函数无界 if(fabs(Min-Max)<eps){ flag=0; break; } */ //此题不会出现无解情况 //交换非基本变量和基本变量名字 double tmp=matrix[chu][0]; matrix[chu][0]=matrix[0][ru]; matrix[0][ru]=tmp; //先修改表格matrix[chu][ru] matrix[chu][ru]=1.0/matrix[chu][ru]; //修改表格的主元行 for(int j=1;j<=r+1;j++){ if(j==ru) continue; matrix[chu][j]*=matrix[chu][ru]; } //修改表格中其他单元格 for(int i=1;i<=m+1;i++){ if(i==chu) continue; for(int j=1;j<=r+1;j++){ if(j==ru) continue; matrix[i][j]-=matrix[chu][j]*matrix[i][ru]; } } //修改表格中主元列 for(int j=1;j<=m+1;j++){ if(j==chu) continue; matrix[j][ru]=-matrix[j][ru]*matrix[chu][ru]; } } /* 解集读取(只是其中一个解,没有多解的情况判断); for(int i=1;i<=r;i++) if(matrix[0][i]!=0.0) printf("x%.0lf=%.2lf\n",matrix[0][i],matrix[m+1][i]); for(int i=1;i<=m;i++) if(matrix[i][0]!=0.0) printf("x%.0lf=%.2lf\n",matrix[i][0],matrix[i][r+1]); printf("\n"); */ /* if(flag==0) printf("该目标函数无界\n"); else if(flag==1) printf("该目标函数有一个最优基本可行解,最优值为%lf\n",matrix[m+1][r+1]); else printf("该目标函数有不止一个最有基本可行解,最优值为%lf\n",matrix[m+1][r+1]); system("pause"); */ printf("%.0lf\n",matrix[m+1][r+1]); } return 0; }