题目链接:https://vjudge.net/contest/68128#problem/A
算法:最大流 - 拆点
思路:把每台机器拆成两个点,中间用一条边连通,并将容量设为该机器的生成电脑的速度,通过机器的产出零件 和 机器的输入零件 来建边,不同机器之间的边容量设为无穷大。从而转化为最大流问题。输出时,将容量比原来小的且除源点汇点和拆点中的边以及反向边外的边输出即可。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <math.h>
#define pi acos(-1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int INF = 0x3f3f3f3f;
const LL ll_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 50 + 10;
const int maxp = 10 + 10;
int Q[maxn], S[maxn][maxp], D[maxn][maxp];
int s, t;
int head[maxn*maxn], cnt=0;
int dis[maxp*2];
struct Edge
{
int from, to, next, cap;
}es[maxn*maxn*2], coe[maxn*maxn*2], link[maxn*maxn*2];
void init()
{
memset(head, -1, sizeof(head));
}
void add(int u, int v, int vol)
{
es[cnt].from = u;
es[cnt].to = v;
es[cnt].cap = vol;
es[cnt].next = head[u]; coe[cnt] = es[cnt];
head[u] = cnt++;
es[cnt].from = v;
es[cnt].to = u;
es[cnt].cap = 0;
es[cnt].next = head[v]; coe[cnt] = es[cnt];
head[v] = cnt++;
}
bool BFS()
{
queue<int> que;
memset(dis, -1, sizeof(dis));
dis[s] = 0;
que.push(s);
int cur, v;
while(!que.empty())
{
cur = que.front(); que.pop();
for(int i=head[cur]; i!=-1; i=es[i].next){
v = es[i].to;
if(dis[v]==-1 && es[i].cap>0){
dis[v] = dis[cur]+1;
que.push(v);
}
}
}
if(dis[t] == -1) return false;
else return true;
}
int DFS(int cur, int low)
{
int res=0;
if(cur == t) return low;
for(int i=head[cur]; i!=-1; i=es[i].next){
if(dis[es[i].to]==dis[cur]+1
&& es[i].cap>0
&& (res = DFS(es[i].to, min(low, es[i].cap))) ){
es[i].cap -= res;
es[i^1].cap += res;
return res;
}
}
return 0;
}
int main()
{
init();
int P, N;
scanf("%d%d", &P, &N);
s = 0; t = 2*N+1;
for(int i=1; i<=N; i++){
scanf("%d", &Q[i]);
int flag1=0, flag2=0;
for(int j=1; j<=P; j++){
scanf("%d", &S[i][j]);
if(S[i][j] == 1) flag1=1;
}
if(flag1 == 0) add(s, 2*i-1, INF);
for(int j=1; j<=P; j++){
scanf("%d", &D[i][j]);
if(D[i][j] == 0) flag2=1;
}
if(flag2 == 0) add(2*i, t, INF);
}
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
if(i == j) {
add(i*2-1, i*2, Q[i]);
continue;
}
int flag = 0;
for(int k=1; k<=P; k++){
if(!(D[i][k]==S[j][k] || S[j][k]==2)){
flag = 1; break;
}
}
if(!flag) add(2*i, 2*j-1, INF);
}
}
int ans=0 , tmp=0;
while(BFS()){
if(tmp = DFS(s, INF))
ans += tmp;
}
printf("%d ", ans);
int tot=0;
for(int i=0; i<cnt; i++){
if(es[i].to%2==0 && es[i].from==es[i].to-1) continue;
if(coe[i].cap == 0 || coe[i].from==s ||coe[i].to==t) continue;
if(coe[i].cap > es[i].cap) {
link[++tot].from = (es[i].from+1)/2;
link[tot].to = (es[i].to+1)/2;
link[tot].cap = coe[i].cap - es[i].cap;
}
}
printf("%d\n", tot);
for(int i=1; i<=tot; i++){
printf("%d %d %d\n", link[i].from, link[i].to, link[i].cap);
}
}