题目链接 :http://poj.org/problem?id=3436
题目很难理解,读题的时候读蒙了,看了好多解释才理解,简单点就是有很多机器来生产电脑,这些机器 可以通过利用一些零件生成或者销毁一些零件,也可能通过一些零件直接生成一台电脑。
利用的零件 给出的输入形式为 0代表这台机器工作的时候不需要这种零件,1代表必须要这种零件,2代表可有可无
工作产生的结果是输出形式为 1代表生成了这种零件,0代表没有生成这种零件
所以建图的时候 需要一个超级源点,一个超级汇点,由于在点上有权值,所以需要拆点
超级源点连接的是 输入形式中没有1的 容量为INF
超级汇点连接的是 输出形式中没有0的 容量为INF
某个点的输出如果是其他某些点的输入,也连起来,容量为INF
剩下的就是普通的最大流了
最后还有输出路径
输出的是那些 机器的输出恰好是机器的输入的那些边
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
const int maxn = 1e6+5;
struct node {
int to;
int cap;
int rev;
int flow;
node(){}
node(int a,int b,int c,int d):to(a),cap(b),flow(c),rev(d){}
};
struct Edge {
int x;
int y;
int c;
};
vector<node> v[maxn];
vector<Edge> vv;
int d[maxn],cur[maxn],n,m,p,s,t,cnt;
void addedge(int from,int to,int cap) {
v[from].push_back(node(to,cap,cap,v[to].size()));
v[to].push_back(node(from,0,0,v[from].size()-1));
}
int dfs(int u,int flow) {
if(u==t || !flow) return flow;
int ans = 0;
for(int &i = cur[u];i<v[u].size();i++) {
node &e = v[u][i];
if(d[e.to] == d[u] + 1 && e.cap > 0) {
int temp = dfs(e.to,min(flow,e.cap));
if(temp>0) {
flow-=temp;
e.cap-=temp;
v[e.to][e.rev].cap+=temp;
ans += temp;
if(!flow) break;
}
}
}
if(!ans) d[u] = -1;
return ans;
}
bool bfs() {
for(int i=0;i<=t;i++) d[i] = -1;
queue<int> q;
q.push(s);
d[s] = 0;
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i=0;i<v[u].size();i++) {
int to = v[u][i].to;
if(d[to]==-1 && v[u][i].cap>0) {
d[to] = d[u] + 1;
q.push(to);
}
}
}
return (d[t] != -1);
}
int dinic() {
int max_flow = 0,tt;
while(bfs()) {
for(int i=s;i<=t;i++) cur[i] = 0;
while((tt = dfs(s,INF)) > 0) max_flow+=tt;
}
return max_flow;
}
int pos[105][105];
int main()
{
while(scanf("%d%d",&p,&n) != EOF) {
vv.clear();
s = 0, t = 2*n + 1;
for(int i=s;i<=t;i++)v[i].clear();
for(int i=1;i<=n;i++) {
for(int j=0;j<2*p+1;j++) {
scanf("%d",&pos[i][j]);
}
}
for(int i=1;i<=n;i++) {
addedge(i,i+n,pos[i][0]);
int flag1=1,flag2=1;
for(int j=1;j<=p;j++) {
if(pos[i][j]==1){
flag1=0;
break;
}
}
if(flag1) addedge(s,i,INF);
for(int j=p+1;j<=2*p;j++) {
if(pos[i][j]==0){
flag2=0;
break;
}
}
if(flag2) addedge(i+n,t,INF);
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(i==j)continue;
int flag=1;
for(int k=1;k<=p;k++) {
if(pos[i][k+p] != pos[j][k] && pos[j][k] != 2) {
flag=0;
break;
}
}
if(flag) {
addedge(i+n,j,INF);
}
}
}
int ans = dinic();cnt=0;
for(int i=n+1;i<=2*n;i++) {
for(int j=0;j<v[i].size();j++) {
if(v[i][j].to != i-n && v[i][j].to>=1 && v[i][j].to <= n && v[i][j].cap != v[i][j].flow) {
Edge temp;
cnt++;
temp.x = i-n;
temp.y = v[i][j].to;
temp.c = v[i][j].flow - v[i][j].cap;
vv.push_back(temp);
}
}
}
printf("%d %d\n",ans,cnt);
if(cnt)
for(int i=0;i<vv.size();i++) {
printf("%d %d %d\n",vv[i].x,vv[i].y,vv[i].c);
}
}
return 0;
}