洛谷1231 教辅的组成
洛谷1231 教輔的組成
https://www.luogu.org/problem/show?pid=1231
題目背景
滾粗了的HansBug在收拾舊語文書,然而他發現了什么奇妙的東西。
題目描述
蒟蒻HansBug在一本語文書里面發現了一本答案,然而他卻明明記得這書應該還包含一份練習題。然而出現在他眼前的書多得數不勝數,其中有書,有答案,有練習冊。已知一個完整的書冊均應該包含且僅包含一本書、一本練習冊和一份答案,然而現在全都亂做了一團。許多書上面的字跡都已經模糊了,然而HansBug還是可以大致判斷這是一本書還是練習冊或答案,并且能夠大致知道一本書和答案以及一本書和練習冊的對應關系(即僅僅知道某書和某答案、某書和某練習冊有可能相對應,除此以外的均不可能對應)。既然如此,HansBug想知道在這樣的情況下,最多可能同時組合成多少個完整的書冊。
輸入輸出格式
輸入格式:
?
第一行包含三個正整數N1、N2、N3,分別表示書的個數、練習冊的個數和答案的個數。
第二行包含一個正整數M1,表示書和練習冊可能的對應關系個數。
接下來M1行每行包含兩個正整數x、y,表示第x本書和第y本練習冊可能對應。(1<=x<=N1,1<=y<=N2)
第M1+3行包含一個正整數M2,表述書和答案可能的對應關系個數。
接下來M2行每行包含兩個正整數x、y,表示第x本書和第y本答案可能對應。(1<=x<=N1,1<=y<=N3)
?
輸出格式:
?
輸出包含一個正整數,表示最多可能組成完整書冊的數目。
?
輸入輸出樣例
輸入樣例#1:5 3 4 5 4 3 2 2 5 2 5 1 5 3 5 1 3 3 1 2 2 3 3 4 3 輸出樣例#1:
2
說明
樣例說明:
如題,N1=5,N2=3,N3=4,表示書有5本、練習冊有3本、答案有4本。
M1=5,表示書和練習冊共有5個可能的對應關系,分別為:書4和練習冊3、書2和練習冊2、書5和練習冊2、書5和練習冊1以及書5和練習冊3。
M2=5,表示數和答案共有5個可能的對應關系,分別為:書1和答案3、書3和答案1、書2和答案2、書3和答案3以及書4和答案3。
所以,以上情況的話最多可以同時配成兩個書冊,分別為:書2+練習冊2+答案2、書4+練習冊3+答案3。
數據規模:
對于數據點1, 2, 3,M1,M2<= 20
對于數據點4~10,M1,M2 <= 20000
拆點+最大流
為什么要拆點?
以為一般的最大流可一個點經過多次,而本題一個點只能經過1次,所以要拆成一個流量為1的邊
#include<cstdio> #include<cstring> #include<algorithm> #define N 10000 #define M 20001 using namespace std; int n1,n2,n3,m1,m2,tot=1,src,dec,ans,cur[N*5],lev[N*5],head,tail,que[4*5*N],tmp; int front[N*5]; struct node {int to,next,cap; }e[M*10]; inline void add(int u,int v) {e[++tot].to=v;e[tot].next=front[u];e[tot].cap=1;front[u]=tot;e[++tot].to=u;e[tot].next=front[v];e[tot].cap=0;front[v]=tot; } inline bool bfs() {for(int i=0;i<=N*5;i++) {lev[i]=-1;cur[i]=front[i];}head=tail=0;que[tail++]=src;lev[src]=0;while(head<tail){int now=que[head];for(int i=front[now];i;i=e[i].next){int to=e[i].to;if(e[i].cap>0&&lev[to]==-1){lev[to]=lev[now]+1;que[tail++]=to;if(to==dec) return true;}}head++;}return false; } inline int dinic(int now,int flow) {if(now==dec) return flow;int res=0,delta;for(int & i=cur[now];i;i=e[i].next){int to=e[i].to;if(e[i].cap>0&&lev[to]>lev[now]) {delta=dinic(to,min(e[i].cap,flow-res));if(delta){e[i].cap-=delta;e[i^1].cap+=delta;res+=delta;if(res==flow) break;}} }if(res!=flow) lev[now]=-1;return res; } int main() {scanf("%d%d%d",&n1,&n2,&n3);src=0;dec=4*N+1;for(int i=1;i<=n3;i++) add(src,i);for(int i=1;i<=n1;i++) add(N+i,N*2+i);for(int i=1;i<=n2;i++) add(i+3*N,dec);int x,y;scanf("%d",&m1);for(int i=1;i<=m1;i++) {scanf("%d%d",&x,&y);add(x+2*N,y+3*N);}scanf("%d",&m2);for(int i=1;i<=m2;i++){scanf("%d%d",&x,&y);add(y,x+N);}while(bfs()) ans+=dinic(src,n3);printf("%d",ans); }bfs中去掉if(to==des) reurn true
改為在最后return錢加一個?if(lev[dec]!=-1) return true;
前者比后者快。
原因:因為是bfs
轉載于:https://www.cnblogs.com/TheRoadToTheGold/p/6431332.html
總結
以上是生活随笔為你收集整理的洛谷1231 教辅的组成的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络路径无法访问问题的解决
- 下一篇: 邓迎春绘画201702作品08