#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
int P; // 零件数量
int N; // 机器数量
// 为了最后的打印结果,需要保存流的变化过程
const int MAXSIZE = 120;
int backup[MAXSIZE][MAXSIZE];
int input[MAXSIZE][15];
int output[MAXSIZE][15];
int road[MAXSIZE][MAXSIZE];
int visit[MAXSIZE];
int pre[MAXSIZE];
int start, end;
const int INF = 0x3f3f3f3f;
queue<int> Q;
bool canrun(int x, int y){
// 遍历y, 去x中查找
for (int i = 1; i <= P ; ++i) {
if (input[y][i] == 2)continue;
if (input[y][i] == 1&&output[x][i]==1) continue;
if (input[y][i] == 0&&output[x][i]==0) continue;
else
return false;
}
return true;
}
bool isstart(int x){
for (int i = 1; i <=P ; ++i) {
if (input[x][i]==1)return false;
}
return true;
}
bool isend(int x){
for (int i = 1; i <=P ; ++i) {
if (output[x][i]!=1)return false;
}
return true;
}
bool getpath(int s, int e){
memset(visit, 0, sizeof(visit));
memset(pre, -1, sizeof(pre));
while (!Q.empty())
Q.pop();
Q.push(s);
visit[s] = 1;
while (!Q.empty()){
int temp = Q.front();
Q.pop();
if (temp == e)
return true;
for (int i = 1; i <=e ; ++i) {
if (road[temp][i]&&!visit[i]){
visit[i] = 1;
pre[i] = temp;
Q.push(i);
}
}
}
return false;
}
int EK(int s, int e){
int ans = 0;
while (getpath(s, e)){
int t = e;
int cur = INF;
while (pre[t]!=-1){
cur = min(cur, road[pre[t]][t]);
t = pre[t];
}
// update the edge
t = e;
while (pre[t]!=-1){
road[pre[t]][t] -= cur;
road[t][pre[t]] += cur;
t = pre[t];
}
ans += cur;
}
return ans;
}
int main(){
// freopen("../in.txt", "r", stdin);
while (cin>>P>>N){
memset(road, 0, sizeof(road));
for (int i = 1; i <=N ; ++i) {
// 直接进行拆点
cin>>road[2*i-1][2*i];
for (int j = 1; j <=P ; ++j) {
cin>>input[i][j];
}
for (int j = 1; j <=P ; ++j) {
cin>>output[i][j];
}
}
// 数据读取完成
// 然后进行构图
for (int i = 1; i <=N ; ++i) {
for (int j = 1; j <=N ; ++j) {
if (i == j) continue;
// 检查机器i---->j是否可行
// 查看机器i的输出和机器j的输入即可
if (canrun(i, j)){
road[2*i][2*j-1] = INF;
}
}
}
// 搭建超级源点和超级汇点
// N+1为源点, N+2为汇点
start = 2*N+1, end = 2*N+2;
for (int i = 1; i <=N ; ++i) {
if (isstart(i)){
road[start][2*i-1] = INF;
}
if (isend(i)){
road[2*i][end] = INF;
}
}
for (int i = 0; i < MAXSIZE; ++i) {
for (int j = 0; j < MAXSIZE; ++j) {
backup[i][j] = road[i][j];
}
}
// 网路搭建完成
// 利用EK算法解决最大流问题
cout<<EK(start, end)<<" ";
int num = 0;
for (int i = 1; i <=N ; ++i) {
for (int j = 1; j <= N ; ++j) {
if (i == j) continue;
if (backup[2*i][2*j-1]!=road[2*i][2*j-1])
num++;
}
}
cout<<num<<endl;
for (int i = 1; i <=N ; ++i) {
for (int j = 1; j <= N ; ++j) {
if (backup[2*i][2*j-1]&&backup[2*i][2*j-1]!=road[2*i][2*j-1])
cout<<i<<" "<<j<<" "<<backup[2*i][2*j-1]-road[2*i][2*j-1]<<endl;
}
}
}
}
POJ 3436
最新推荐文章于 2019-08-23 00:36:31 发布