教輔的組成(最大流)
教輔的組成
https://www.luogu.org/problemnew/show/P1231
題目背景
滾粗了的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)
輸出格式:
輸出包含一個正整數,表示最多可能組成完整書冊的數目。
輸入輸出樣例
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
與這題是相同的題型
https://www.cnblogs.com/Fighting-sh/p/9818674.html
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<cstdio> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 #define maxn 200005 11 #define MAXN 200005 12 #define mem(a,b) memset(a,b,sizeof(a)) 13 const int N=200005; 14 const int M=200005; 15 const int INF=0x3f3f3f3f; 16 using namespace std; 17 int n; 18 struct Edge{ 19 int v,next; 20 int cap,flow; 21 }edge[MAXN*20];//註意這裏要開的夠大。。不然WA在這裏真的想罵人。。問題是還不報RE。。 22 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN]; 23 int cnt=0;//實際存儲總邊數 24 void isap_init() 25 { 26 cnt=0; 27 memset(pre,-1,sizeof(pre)); 28 } 29 void isap_add(int u,int v,int w)//加邊 30 { 31 edge[cnt].v=v; 32 edge[cnt].cap=w; 33 edge[cnt].flow=0; 34 edge[cnt].next=pre[u]; 35 pre[u]=cnt++; 36 } 37 void add(int u,int v,int w){ 38 isap_add(u,v,w); 39 isap_add(v,u,0); 40 } 41 bool bfs(int s,int t)//其實這個bfs可以融合到下面的叠代裏,但是好像是時間要長 42 { 43 memset(dep,-1,sizeof(dep)); 44 memset(gap,0,sizeof(gap)); 45 gap[0]=1; 46 dep[t]=0; 47 queue<int>q; 48 while(!q.empty()) 49 q.pop(); 50 q.push(t);//從匯點開始反向建層次圖 51 while(!q.empty()) 52 { 53 int u=q.front(); 54 q.pop(); 55 for(int i=pre[u];i!=-1;i=edge[i].next) 56 { 57 int v=edge[i].v; 58 if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//註意是從匯點反向bfs,但應該判斷正向弧的余量 59 { 60 dep[v]=dep[u]+1; 61 gap[dep[v]]++; 62 q.push(v); 63 //if(v==sp)//感覺這兩句優化加了一般沒錯,但是有的題可能會錯,所以還是註釋出來,到時候視情況而定 64 //break; 65 } 66 } 67 } 68 return dep[s]!=-1; 69 } 70 int isap(int s,int t) 71 { 72 if(!bfs(s,t)) 73 return 0; 74 memcpy(cur,pre,sizeof(pre)); 75 //for(int i=1;i<=n;i++) 76 //cout<<"cur "<<cur[i]<<endl; 77 int u=s; 78 path[u]=-1; 79 int ans=0; 80 while(dep[s]<n)//叠代尋找增廣路,n為節點數 81 { 82 if(u==t) 83 { 84 int f=INF; 85 for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增廣路 86 f=min(f,edge[i].cap-edge[i].flow); 87 for(int i=path[u];i!=-1;i=path[edge[i^1].v]) 88 { 89 edge[i].flow+=f; 90 edge[i^1].flow-=f; 91 } 92 ans+=f; 93 u=s; 94 continue; 95 } 96 bool flag=false; 97 int v; 98 for(int i=cur[u];i!=-1;i=edge[i].next) 99 { 100 v=edge[i].v; 101 if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow) 102 { 103 cur[u]=path[v]=i;//當前弧優化 104 flag=true; 105 break; 106 } 107 } 108 if(flag) 109 { 110 u=v; 111 continue; 112 } 113 int x=n; 114 if(!(--gap[dep[u]]))return ans;//gap優化 115 for(int i=pre[u];i!=-1;i=edge[i].next) 116 { 117 if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x) 118 { 119 x=dep[edge[i].v]; 120 cur[u]=i;//常數優化 121 } 122 } 123 dep[u]=x+1; 124 gap[dep[u]]++; 125 if(u!=s)//當前點沒有增廣路則後退一個點 126 u=edge[path[u]^1].v; 127 } 128 return ans; 129 } 130 131 int main(){ 132 int nn,mm,s,t; 133 int F,D; 134 cin>>n>>F>>D; 135 int a,b,c; 136 isap_init(); 137 cin>>nn; 138 for(int i=1;i<=nn;i++){ 139 cin>>a>>b; 140 add(b,a+F,1); 141 } 142 cin>>mm; 143 for(int i=1;i<=mm;i++){ 144 cin>>a>>b; 145 add(a+F+n,F+n+n+b,1); 146 } 147 for(int i=1;i<=F;i++){ 148 add(0,i,1); 149 } 150 for(int i=1;i<=D;i++){ 151 add(F+n+n+i,F+n+n+D+1,1); 152 } 153 for(int i=1;i<=n;i++){ 154 add(F+i,F+n+i,1); 155 } 156 s=0,t=F+n+n+D+1; 157 n=F+n+n+D+2; 158 cout<<isap(s,t)<<endl; 159 }View Code
教輔的組成(最大流)