/* 题意:有N家公司和N家银行,这N家公司只会向N家银行借贷,N家银行也只借贷给N家公司,被pol**e查账,查出 N家公司分别借贷了SR[i],N家银行分别借出了SC[i],交易额限制在100以下(这个地方没看到,悲剧WA);求这 样的借贷是否合理,合理则输出合法交易的矩阵。 题解:最大流; 建图:加入源点,在源点和银行之间加入有向边,权值为该银行借出的金额,银行和公司之间分别加入权值为100 的有向边,每间银行都指向所有的公司,加入汇点,在所有公司和汇点之间加入有向边,权值为公司所借的金额 数,求出最大流,然后银行和公司之间的边的权值的变化即为所求解。遍历所有边一次记录到矩阵中。 */ #include <iostream> #include <cstring> using namespace std; #define EMAX 20500 #define VMAX 250 const int INF = 0xfffffff; int head[VMAX],dis[VMAX],cur[VMAX],gap[VMAX],pre[VMAX]; int map[VMAX][VMAX]; int EN; struct edge { int from,to; int weight; int next; }e[EMAX]; void insert(int u,int v,int w) { e[EN].from = u; e[EN].to = v; e[EN].weight = w; e[EN].next = head[u]; head[u] = EN++; e[EN].weight = 0; e[EN].from = v; e[EN].to = u; e[EN].next = head[v]; head[v] = EN++; } int sap(int s,int t, int n)//sap模版 { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); for(int i=0; i<=n; i++) cur[i] = head[i]; int u = pre[s]; pre[s] = s; int ret = 0; int temp = -1; gap[0] = n; bool flag; while(dis[s] < n) { flag = false; for(int &i = cur[u]; i != -1; i = e[i].next) { int v = e[i].to; if(e[i].weight && dis[u] == dis[v] + 1) { if (temp == -1 || temp>e[i].weight) temp = e[i].weight; pre[v] = u; u = v; if(v == t) { ret += temp; for(u = pre[u];v != s;v = u,u = pre[u]) { e[cur[u]].weight -= temp; e[cur[u]^1].weight += temp; } temp = -1; } flag = true; break; } } if (flag) continue; int mindis = n; for(int i = head[u]; i != -1 ; i = e[i].next) { int v = e[i].to; if(e[i].weight && mindis > dis[v]) { cur[u] = i; mindis = dis[v]; } } gap[dis[u]]--; if( gap[dis[u]] == 0) break; dis[u] = mindis+1; gap[dis[u]]++; u = pre[u]; } return ret; } int main(void) { int n,t,sum; while (cin >> n) { sum = 0; memset(head,-1,sizeof(head)); memset(map,0,sizeof(map)); EN = 0; for(int i=1; i<=n; i++) { cin >> t; sum += t; insert(0,i,t);//源点连接 } for(int i=1; i<=n; i++) { cin >> t; insert(n+i,2*n+1,t);//汇点连接 } for(int i=1; i<=n; i++) for(int j=1; j<=n; j++)//公司和银行连接 insert(i,n+j,100); if (sum == sap(0,n+n+1,n+n+2)) { cout << "YES" << endl; for(int u=1; u<=n; u++)//遍历所有边并且记录值 { for(int i=head[u]; i!=-1; i=e[i].next) { if (e[i].to != 0) { map[u][e[i].to-n] = e[i^1].weight; } } } for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if (j == 1) cout << map[i][j]; else cout << " " << map[i][j]; } cout << endl; } } else cout << "NO" << endl; } return 0; }
toj 1421 最大流sap,布布扣,bubuko.com
原文:http://www.cnblogs.com/toufu/p/3614961.html