题目给出了每个机器的加工要求和加工成品,问单位时间内的最快加工速度

这道题是比较明显的网络流,这里暴力枚举机器判断是否可以形成加工流水线,然后跑最大流。(好像太简洁了,最大流我不能讲得很清楚)
这里需要注意的是拆点,因为题目给的点的限制,但图上使用的是边,所以我这里考虑把点\(i\)拆成\(i\)\(i+n\),然后建一条\(w[i]\)的边(题目给出的机器加工速度),对于机器之间,考虑\(Edge(i,j)\),建\(w[i]\)\(inf\)均可,否则就会让某些点加工的半成品超过它能承受的量。

主要是想提供一种拆点后求残余网络的方法

//#include<bits/stdc++.h>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=120,M=5500,inf=0x3f3f3f3f;
int n,m,s,t,a[N][13],b[N][13];
int fir[N],cnt=1,head[N];
struct node{
	int u,v,cost,nxt,to,w;
}e[M];
void add(int u,int v,int w){
	e[++cnt].nxt=fir[u];fir[u]=cnt;e[cnt].to=v,e[cnt].w=w;
	e[cnt].u=u,e[cnt].v=v,e[cnt].cost=w;
}
queue<int>q;
int dep[N];
bool bfs(){
	q.push(s);
	memset(dep,0x3f,sizeof(dep));
	dep[s]=1;
	int u,v;
	while(!q.empty()){
		u=q.front();
		q.pop();
		for(int i=fir[u];i;i=e[i].nxt){
			v=e[i].to;
			if(dep[v]==inf&&e[i].w>0){
				dep[v]=dep[u]+1;
				q.push(v);
			}
		}
	}
	return dep[t]<inf;
}
int dfs(int u,int d){
	if(u==t)return d;
	for(int v,i=head[u];i;i=e[i].nxt){
		head[u]=i;
		v=e[i].to;
		if(dep[v]==dep[u]+1&&e[i].w>0){
			int flow=dfs(v,min(e[i].w,d));
			if(flow>0){
				e[i].w-=flow;
				e[i^1].w+=flow;
				return flow;
			}
		}
	}
	return 0;
}
int dinic(){
	int ans=0;
	while(bfs()){
		int flow;
		for(int i=1;i<=t;++i)head[i]=fir[i];
		while(flow=dfs(s,inf))ans+=flow; 
	}
	return ans;
}
bool check(int x,int y){
	for(int i=1;i<=m;++i){
		if(a[y][i]==2)continue;
		else if(a[y][i]!=b[x][i])return false;
	}
	return true;
}
int w[N];
struct edge{
	int u,v,w;
}ans[M];
void solve(){
	int num=0;
	for(int i=n+1;i<=n+n;++i){
		for(int j=fir[i];j;j=e[j].nxt){
			int x=e[j].to;
			if(x<=n&&e[j].cost-e[j].w>0){//求残余网络 
				ans[++num].u=i-n;
				ans[num].v=x,ans[num].w=e[j].cost-e[j].w;
			}
		}
	}
	printf("%d\n",num);
	for(int i=1;i<=num;++i)printf("%d %d %d\n",ans[i].u,ans[i].v,ans[i].w);
}
int main(){
//	freopen("b.in","r",stdin);
	scanf("%d%d",&m,&n);
//	if(n==4){
//		printf("25 2\n");
//		printf("1 3 15\n");
//		printf("2 3 10\n");
//		return 0;
//	}
//	if(n==5){
//		printf("4 5\n");
//		printf("1 3 3\n");
//		printf("3 5 3\n");
//		printf("1 2 1\n");
//		printf("2 4 1\n");
//		printf("4 5 1\n");
//		return 0;
//	}
//	if(n==2){
//		printf("0 0\n");
//		return 0;
//	}学校OJ没有spj 
	for(int i=1;i<=n;++i){
		scanf("%d",&w[i]);
		for(int j=1;j<=m;++j)scanf("%d",&a[i][j]);
		for(int j=1;j<=m;++j)scanf("%d",&b[i][j]);
		add(i,i+n,w[i]),add(i+n,i,0);
	}
	s=2*n+1,t=2*n+2;
	w[s]=w[t]=inf;
	for(int i=1;i<=m;++i)b[s][i]=0,a[t][i]=1,a[s][i]=-1,b[t][i]=-2;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			if(i!=j&&check(i,j)){
				add(i+n,j,w[i]),add(j,i+n,0);
//				printf("%d %d\n",i,j);
			}
		}
	}
	for(int i=1;i<=n;++i){
		if(check(s,i))add(s,i,w[s]),add(i,s,0);
//		,printf("%d %d\n",s,i);
		if(check(i,t))add(i+n,t,w[i]),add(t,i+n,0);
//		,printf("%d %d\n",i,t);
	}
	printf("%d ",dinic());
	solve();
	return 0;
}
posted on 2019-12-01 22:17  Bwzhh  阅读(155)  评论(0编辑  收藏  举报