教辅的组成
題目背景
滾粗了的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
思路:網絡流構圖+最大流+拆點
一開始,我是把s與書相連,書與教輔相連,然后教輔與答案相連,然后W0了。
因為,教輔也只有一份的,所以還要教輔與教輔相連。
然后又W10了,因為,書才是承上啟下的。
代碼實現:
1 #include<cstdio> 2 #include<cstring> 3 const int inf=1e8; 4 const int maxn=80000; 5 const int maxm=800000; 6 int n1,n2,n3,m1,m2,s,t,ans; 7 int a,b,c; 8 inline int min_(int x,int y){return x<y?x:y;} 9 int h[maxn],hs=1; 10 struct edge{int s,n,w;}e[maxm]; 11 void add(int q,int z){ 12 e[++hs]=(edge){z,h[q],1},h[q]=hs; 13 e[++hs]=(edge){q,h[z]},h[z]=hs; 14 } 15 int d[maxn],q[maxn],head,tail; 16 void bfs(){ 17 memset(d,0,sizeof(d)); 18 head=tail=0; 19 q[head++]=s,d[s]=1; 20 while(head>tail){ 21 a=q[tail++]; 22 for(int i=h[a];i;i=e[i].n) 23 if(!d[e[i].s]&&e[i].w){ 24 d[e[i].s]=d[a]+1; 25 if(e[i].s==t) return; 26 q[head++]=e[i].s; 27 } 28 } 29 } 30 int ap(int k,int w){ 31 if(k==t) 32 return w; 33 int uw=w; 34 for(int i=h[k];i&&uw;i=e[i].n) 35 if(d[e[i].s]==d[k]+1&&e[i].w){ 36 int nw=ap(e[i].s,min_(uw,e[i].w)); 37 if(nw) e[i].w-=nw,e[i^1].w+=nw,uw-=nw; 38 else d[e[i].s]=0; 39 } 40 return w-uw; 41 } 42 void Dinic(){while(bfs(),d[t]) ans+=ap(s,inf);} 43 int main(){ 44 scanf("%d%d%d",&n2,&n1,&n3); 45 s=0,t=n1+n1+n2+n3+1; 46 for(int i=1;i<=n1;i++) add(s,i); 47 for(int i=1;i<=n2;i++) add(i+n1,i+n1+n2); 48 for(int i=1;i<=n3;i++) add(i+n1+n2+n2,t); 49 scanf("%d",&m1); 50 for(int i=1;i<=m1;i++) scanf("%d%d",&b,&a),add(a,b+n1); 51 scanf("%d",&m2); 52 for(int i=1;i<=m2;i++) scanf("%d%d",&a,&b),add(a+n1+n2,b+n1+n2+n2); 53 Dinic(); 54 printf("%d\n",ans); 55 return 0; 56 }題目來源:洛谷
轉載于:https://www.cnblogs.com/J-william/p/6599579.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: Oracle 基础系列之1.1 ora
- 下一篇: 机器学习如何应用到实际生活和创业中