前言及感悟:
网络流重在对题目的转化之后的建图.需要仔细思考.
题意:
给定N个机器,生产P种零件。对于每种机器都有输入规格和输出规格和生产效率(即单位时间生产多少个)
要求输出最大生产量和能生产最大生产量的线路上的生产边的多少。
然后依次输出能满足的生产线上的生产信息.
思路:
对于每个机器,我们将它拆点,看成一个入点和一个出点。
首先,自己的出入和自己的输出可以满足,连边,边的容量为生产的效率.
然后看和其他是否能满足,如果满足,则建立一条无穷大的边.
怎么看是否满足?对于一个机器,它如果有必须要的输入零件,那么很显然,匹配的机器也要能输出这种生产的零件。(不然生产出来报废?)
那么这里的建边就是判断当前点的输出规格是否满足其他点的输入规格,满足就连输出到输入的边.
为何建立无穷大的边?这就是对这题的转化剖析。
首先一个点肯定要先经过自己本身的生产,然后再去经过其他的机器的生产。(这里可以画图理解)
那么很显然每条满足的生产线路上的最大输出量肯定是这条路上的机器的最小的生产效率.
那么建无穷大的边不会影响这个值.
那么最大生产量很显然就是最大流了,然后能满足的线路的话就是说明减少了的边.
因为如果这条边的容量减少了,那么很显然就说明这条边是在最大流上的边。
减少了的量就是INF-now。
然后再遍历一次输出能满足的每条边的信息
PS:vj的样例错了...
Code:

#include<iostream> #include<stdio.h> #include<queue> #include<algorithm> #include<math.h> #include<stack> #include<map> #include<limits.h> #include<vector> #include<string.h> #include<string> using namespace std; typedef long long LL; typedef pair<double,double> pii; const int N = 55; const int M = 1005; const int Mod = 1e9+7; #define pi acos(-1) #define INF 1e8 #define INM INT_MIN #define pb(a) push_back(a) #define mk(a,b) make_pair(a,b) #define dbg(x) cout << "now this num is " << x << endl; #define met0(axx) memset(axx,0,sizeof(axx)); #define metf(axx) memset(axx,-1,sizeof(axx)); #define sd(ax) scanf("%d",&ax) #define sld(ax) scanf("%lld",&ax) #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx) #define sdd(ax,bx) scanf("%d %d",&ax,&bx) #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx) #define sfd(ax) scanf("%lf",&ax) #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx) #define pr(a) printf("%d\n",a) #define plr(a) printf("%lld\n",a) struct Node{int to,dis,next;}e[M<<1]; int head[N<<1],cnt = -1,val[N<<1],in[55][15],out[55][15]; int dep[N<<1],s,t,p,n; inline void add(int u,int v,int w) { e[++cnt].to = v,e[cnt].dis = w,e[cnt].next = head[u],head[u] = cnt; } bool bfs() { metf(dep);dep[s] = 0; queue<int> Q;Q.push(s); while(!Q.empty()) { int u = Q.front();Q.pop(); for(int i=head[u];i!=-1;i=e[i].next) { int v = e[i].to; if(dep[v] == -1 && e[i].dis > 0) { dep[v] = dep[u]+1; Q.push(v); } } } return dep[t] != -1; } int dfs(int x,int flow) { if(x == t) return flow; int minflow; for(int i=head[x];i!=-1;i=e[i].next) { int v = e[i].to; if(dep[v] == dep[x]+1 && e[i].dis > 0 && (minflow = dfs(v,min(flow,e[i].dis)))) { e[i].dis -= minflow; e[i^1].dis += minflow; return minflow; } } return 0; } int dinic() { int ans = 0; while(bfs()) { ans += dfs(s,INF); } return ans; } bool check(int x,int y) { for(int i=1;i<=p;++i) { if((out[x][i] == 1 && in[y][i] == 0) || (out[x][i] == 0 && in[y][i] == 1)) return false; } return true; } int main() { while(~sdd(p,n)) { metf(head);cnt = -1; s = 0,t = 2*n+1; for(int i=1;i<=n;++i) { sd(val[i]); int f1 = 0,f2 = 0; for(int j=1;j<=p;++j) { sd(in[i][j]); if(in[i][j] == 1) f1 = 1; } for(int j=1;j<=p;++j) { sd(out[i][j]); if(out[i][j] == 0) f2 = 1; } if(!f1) add(s,i,INF),add(i,s,0); if(!f2) add(i+n,t,INF),add(t,i+n,0); add(i,i+n,val[i]),add(i+n,i,0); } for(int i=1;i<=n;++i) { bool f = 0; for(int j=1;j<=n;++j) { if(i == j) continue; if(check(i,j)) { add(i+n,j,INF); add(j,i+n,0); } } } int ans = dinic(); if(ans == 0) printf("0 0\n"); else { int te = 0; for(int i=n+1;i<=2*n;++i) { for(int j=head[i];j!=-1;j=e[j].next) { if(e[j].to != (i-n) && e[j].to != s && e[j].to != t && e[j].dis != INF) te++; } } printf("%d %d\n",ans,te); for(int i=n+1;i<=2*n;++i) { for(int j=head[i];j!=-1;j=e[j].next) { if(e[j].to != (i-n) && e[j].to != s && e[j].to != t && e[j].dis != INF) { int tmp = INF-e[j].dis; printf("%d %d %d\n",i-n,e[j].to,tmp); } } } } } //system("pause"); return 0; }