POJ-3436 ACM Computer Factory
阿新 • • 發佈:2018-11-10
網路流+拆點+源點匯點
首先題意比較難理解,大意是有p種部件和n個機器,每個機器有產量和輸入輸出規格
p=3的情況下,一個機器按照這種形式描述:100 0 1 2 1 1 1
意思為機器產量為100,輸入電腦要求為:沒有部件1,有部件2,部件3可有可無
輸出部件1,2,3都有的電腦
一開始是沒有任何部件的電腦,通過這些機器,要讓所有部件都有的電腦產量最大
然後輸出產量,機器之間的流量個數,還有流量資訊(u,v,w)
把每個機器化為兩個點,輸入點和輸出點,之間連一條邊,容量就是機器產量
按照輸入輸出要求在機器之間加邊,容量為INF
建立沒有部件電腦的輸出點(源點),和所有部件都有的電腦的輸入點(匯點)
再和符合規格的機器加邊
用網路流模板跑一遍(源點->匯點),再過一遍邊得到流量資訊輸出
我用了ISAP模板
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int N=50+10; const int M=2500+10; const int INF=0x7f7f7f7f; struct Edge { int to,nxt,cap,flow; }edge[M]; int tot,first[N]; void addedge(int u,int v,int w,int rw=0) { edge[tot].to=v;edge[tot].cap=w;edge[tot].flow=0; edge[tot].nxt=first[u];first[u]=tot++; edge[tot].to=u;edge[tot].cap=rw;edge[tot].flow=0; edge[tot].nxt=first[v];first[v]=tot++; } void init() { tot=0; memset(first,-1,sizeof(first)); } int gap[N],dep[N],pre[N],cur[N]; int sap(int s,int e,int n) //起點,終點,點個數 { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,first,sizeof(first)); int u=s; pre[u]=-1; gap[0]=n; int ans=0; while(dep[s]<n) { if(u==e) { int Min=INF; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) if(Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u=s; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];i!=-1;i=edge[i].nxt) { v=edge[i].to; if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=n; for(int i=first[u];i!=-1;i=edge[i].nxt) if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=s) u=edge[pre[u]^1].to; } return ans; } int q[N]; int g[N][N]; int main() { int p,n; while(~scanf("%d%d",&p,&n)) { init(); for(int i=0;i<2*p;i++) g[0][i]=0; for(int i=0;i<2*p;i++) g[2*n+1][i]=1; for(int i=1;i<=2*n;i+=2) { scanf("%d",&q[i]); addedge(i,i+1,q[i],0); for(int j=0;j<p;j++) scanf("%d",&g[i][j]); for(int j=0;j<p;j++) scanf("%d",&g[i+1][j]); } for(int i=1;i<=2*n+1;i+=2) { for(int j=0;j<=2*n;j+=2) { bool flag=true; for(int k=0;k<p;k++) if(g[i][k]!=g[j][k]&&g[i][k]!=2&&g[j][k]!=2) { flag=false; continue; } if(flag) addedge(j,i,INF,0); } } int ans=sap(0,2*n+1,2*n+2); int cnt=0; for(int i=2;i<=2*n;i+=2) { for(int j=first[i];j!=-1;j=edge[j].nxt) if(edge[j].flow>0&&edge[j].to!=2*n+1) cnt++; } printf("%d %d\n",ans,cnt); for(int i=2;i<=2*n;i+=2) { for(int j=first[i];j!=-1;j=edge[j].nxt) if(edge[j].flow>0&&edge[j].to!=2*n+1) printf("%d %d %d\n",i/2,edge[j].to/2+1,edge[j].flow); } } return 0; }