题意:一个电脑有P个部件组成,刚开始所有电脑都是空壳子,当一个电脑具备了所有的N个部件则认为这个电脑早好了。现在有一些机器专门加工电脑,每个机器可以加工某一些特性状态原型机,比如必须具备1部件,必须没有3部件,2部件有没有都行,然后这些原型机经过这个机器的加工,就会变成一种特定状态,比如具备123部件,没有45部件。每个机器每小时可以加工qi个原型机。
求出每小时最多生产多少个成品机。以及流水线的运作情况。
题解:题意特别绕。。。。但是题解是很显然的网络流。对于每个机器,拆成一个入点和出点,入点->出点链接一个容量qi的边。然后二重枚举机器,如果第i个机器的输出可以做得第j个机器的输入,那么就链接i的出点->j的入点,容量INF。然后再开一个超级源,如果裸机可以作为i点的输入,就链接源->i的入点,容量INF。如果第i个机器产出成品机,那就链接i的出点->汇,容量INF。
这里机器的每小时加工数量在入点-出点的边限制住了。
很裸的网络流。。。和网络流基本的油管运输问题基本一摸一样。
Code:
#include<stdio.h>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 55;
const int maxp = 15;
const int INF = 0x3f3f3f3f;
int in[maxn*2][maxp],out[maxn][maxp],q[maxn];
int tot,first[maxn],nxt[maxn*maxn],des[maxn*maxn],flow[maxn*maxn];
int dep[maxn];
int ss,tt;
int p,n;
inline void addEdge(int x,int y,int z){
tot++;
des[tot] =y;
flow[tot] =z;
nxt[tot] = first[x];
first[x] = tot;
tot++;
des[tot] =x;
flow[tot] =0;
nxt[tot] = first[y];
first[y] = tot;
}
void init(){
ss=1;tt=2*n+2;
tot =-1;
}
void input(){
// scanf("%d%d",&p,&n);
for (int i=2;i<=n+1;i++){
scanf("%d",q+i);
for (int j=0;j<p;j++){
scanf("%d",&in[i][j]);
}
for (int j=0;j<p;j++){
scanf("%d",&out[i][j]);
}
}
}
void build (){
memset(first,-1,sizeof first);
for (int i=2;i<=n+1;i++){
addEdge(i,i+n,q[i]);
bool flag =true;
for (int j=0;j<p;j++){
if (in[i][j]==1){
flag = false;
break;
}
}
if (flag){
addEdge(ss,i,INF);
}
flag = true;
for (int j=0;j<p;j++){
if (out[i][j]!=1){
flag = false;
break;
}
}
if (flag){
addEdge(i+n,tt,INF);
}
}
for (int i=2;i<=1+n;i++){
for (int j=2;j<=1+n;j++){
if (i==j)continue;
bool flag = true;
for (int k=0;k<p;k++){
if (out[i][k]==in[j][k]||in[j][k]==2)continue;
else{
flag = false;
break;
}
}
if (flag){
addEdge(i+n,j,INF);
}
}
}
}
bool bfs(){
// cout<<"bfs"<<endl;
queue<int> Q;
memset(dep,-1,sizeof dep);
dep[ss]=0;
Q.push(ss);
while (!Q.empty()){
int q = Q.front();Q.pop();
for (int t = first[q];t!=-1;t=nxt[t]){
int v = des[t];
int c = flow[t];
if (c&&dep[v]==-1){
dep[v] = dep[q]+1;
Q.push(v);
}
}
}
return dep[tt]!=-1;
}
int dfs(int node,int now){
// cout<<"dfs"<<endl;
if (node==tt)return now;
int ret =0;
for (int t= first[node];t!=-1&&ret<now;t=nxt[t]){
int v = des[t];
int c = flow[t];
if (dep[v]==dep[node]+1&&c){
int x = min(c,now-ret);
x = dfs(v,x);
flow[t]-=x;
flow[t^1]+=x;
ret+=x;
}
}
if (!ret)dep[node] =-1;
return ret;
}
int max_flow(){
int tot =0;
while (bfs()){
int del;
while (del=dfs(ss,INF)){
tot+=del;
}
}
return tot;
}
void solve(){
int ans =max_flow();
vector<pair<pair<int,int>,int> >list;
for (int i=2;i<=n+1;i++){
for (int t = first[i];t!=-1;t = nxt[t]){
int v = des[t];
int c = flow[t];
if (c&&v>n+1&&v!=2*n+2&&v!=i+n){
// printf("%d %d %d\n",v-n-1,i-1,c);
list.push_back(make_pair(make_pair(v-n-1,i-1),c));
}
}
}
printf("%d %d\n",ans,list.size());
for (int i=0;i<list.size();i++){
printf("%d %d %d\n",list[i].first.first,list[i].first.second,list[i].second);
}
}
int main(){
while (scanf("%d%d",&p,&n)!=EOF){
init();
input();
build();
solve();
}
return 0;
}