poj3436(拆點最大流)
阿新 • • 發佈:2018-11-13
題意:給你p和n,p代表每臺計算器需要幾個部分組成,n代表有幾個組裝機器,接下來n行,每行第一個數代表這臺機器能夠每小時組裝幾臺,剩下前三個數字表示使用這臺機器需要的前置條件(0代表當前組裝不能有這個部分,1代表得有,2代表無所謂),剩下三個數字表示使用這臺機器後的組裝有那幾個部分,問你最多能組裝多少臺
解題思路:首先最大流,建立一個超級源點,這個源點和所有前三個數字沒有1的機器相連,建立一個超級匯點與所有後三個數字全為1的機器相連,中間所有的機器拆成兩個點,邊權為這個機器每小時的組裝量,拆點的意義就是因為流過這個點的流量有限制
程式碼:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int inf=0x3f3f3f3f; const int maxn=5050; struct sc { int x,y,w; }fna[maxn]; struct node { int val; int x[15]; int y[15]; }a[100]; struct Edge { int fa; int next; int to; int v; int w; }edge[maxn]; int head[maxn],cnt; int pre[maxn],visit[maxn]; int n,p,cot; int Start,End; void add(int u,int v,int w) { edge[cnt].next=head[u];edge[cnt].to=v;edge[cnt].fa=u;edge[cnt].w=w;head[u]=cnt++; edge[cnt].next=head[v];edge[cnt].to=u;edge[cnt].fa=v;edge[cnt].w=0;head[v]=cnt++; } int bfs(int s,int e) { queue<int>q; memset(visit,0,sizeof(visit));memset(pre,-1,sizeof(pre)); q.push(s);visit[s]=1; while(!q.empty()) { int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].w<=0||visit[v]) continue; pre[v]=i;visit[v]=1; if(v==e) return 1; q.push(v); } } return 0; } int EK() { int ans=0; int sub; while(bfs(Start,End)) { sub=inf; int k=pre[End]; while(k!=-1) { sub=min(sub,edge[k].w); k=pre[edge[k].fa]; } k=pre[End]; while(k!=-1) { edge[k].w-=sub; edge[k^1].w+=sub; k=pre[edge[k].fa]; } ans+=sub; } return ans; } int main() { int vis[150][150]; int flag; memset(head,-1,sizeof(head));cnt=0; memset(vis,0,sizeof(vis)); scanf("%d%d",&p,&n); Start=0;End=2*n+1; for(int i=1;i<=n;i++) { scanf("%d",&a[i].val); for(int j=1;j<=p;j++) scanf("%d",&a[i].x[j]); for(int j=1;j<=p;j++) scanf("%d",&a[i].y[j]); } for(int i=1;i<=n;i++) { add(i,i+n,a[i].val); flag=0; for(int j=1;j<=p;j++) if(a[i].x[j]==1) flag=1; if(flag==0) add(Start,i,a[i].val); flag=0; for(int j=1;j<=p;j++) if(a[i].y[j]!=1) flag=1; if(flag==0) add(i+n,End,a[i].val); } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { flag=0; if(i==j) continue; for(int k=1;k<=p;k++) { if(a[j].x[k]==2) continue; if(a[j].x[k]!=a[i].y[k]) flag=1; } if(flag==0) { add(i+n,j,a[i].val); vis[i+n][j]=1; } } int ans=EK(); printf("%d ",ans); for(int i=1;i<=n;i++) for(int j=head[i+n];j!=-1;j=edge[j].next) { if(vis[i+n][edge[j].to]&&edge[j].w<a[i].val) cot++; } printf("%d\n",cot); for(int i=1;i<=n;i++) for(int j=head[i+n];j!=-1;j=edge[j].next) { if(vis[i+n][edge[j].to]&&edge[j].w<a[i].val) printf("%d %d %d\n",i,edge[j].to,a[i].val-edge[j].w); } }