洛谷P1231 教辅的组成(网络流)
作者:互联网
题目大意:每本书里面有对应的习题册和答案册,但是现在封面已经模糊不清了,只能判断出默写习题册可能属于某本书,而某些答案册可能属于某本书。给出两种所属的所有可能性,判断出最大可能地组合成一本完整的书的本数。
分析:
此题是三种物品间的匹配问题,建图需要将三种物品的容量全限制为 1 即可。与之前的 洛谷P1402 一样的做法,注意数组的大小。
代码如下:
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #define maxn 40008 #define inf 0x3f3f3f3f using namespace std; typedef long long ll; queue<int> Q; int n,p,q,cnt,S,T; int head[maxn],cur[maxn],d[maxn]; struct Edge{ int to; int val; int next; }edge[maxn<<2]; inline void add(int u,int v,int w){ edge[++cnt].to=v; edge[cnt].val=w; edge[cnt].next=head[u]; head[u]=cnt; return; } bool bfs(){ while(!Q.empty()) Q.pop(); memset(d,-1,sizeof(d)); d[S]=0; Q.push(S); while(!Q.empty()){ int u=Q.front(); Q.pop(); for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].to; if(d[v]==-1&&edge[i].val>0){ d[v]=d[u]+1; Q.push(v); } } } return d[T]!=-1; } int dfs(int u,int flow){ int nowflow=0; if(u==T) return flow; for(int i=cur[u];~i;i=edge[i].next){ cur[u]=i; int v=edge[i].to; if(d[v]==d[u]+1&&edge[i].val>0){ if(int k=dfs(v,min(flow-nowflow,edge[i].val))){ edge[i].val-=k; edge[i^1].val+=k; nowflow+=k; if(nowflow==flow) break; } } } if(!nowflow) d[u]=-1; return nowflow; } int Dinic(){ int ans=0; while(bfs()){ for(int i=0;i<=T;i++) cur[i]=head[i]; ans+=dfs(S,inf); } return ans; } int main() { scanf("%d%d%d",&n,&p,&q); int t,A,B; cnt=-1; memset(head,-1,sizeof(head)); S=0,T=2*n+p+q+1; for(int i=1;i<=p;i++) add(S,i,1),add(i,S,0); for(int i=1;i<=q;i++) add(p+2*n+i,T,1),add(T,p+2*n+i,0); for(int i=1;i<=n;i++) add(p+i,p+n+i,1),add(p+n+i,p+i,0); scanf("%d",&t); for(int i=1;i<=t;i++){ scanf("%d%d",&A,&B); add(B,p+A,1),add(p+A,B,0); } scanf("%d",&t); for(int i=1;i<=t;i++){ scanf("%d%d",&A,&B); add(p+n+A,p+2*n+B,1),add(p+2*n+B,p+n+A,0); } printf("%d\n",Dinic()); }
标签:洛谷,val,nowflow,int,教辅,edge,P1231,maxn,include 来源: https://www.cnblogs.com/Absofuckinglutely/p/12219063.html