1. 程式人生 > >[洛谷1231]教輔的組成

[洛谷1231]教輔的組成

vector oid col n) spfa flow ++ etc amp

思路:

最大流跑三分圖匹配,註意每本書只能用一次,所以把每本書拆成兩個點,連一條邊。
不能直接用EdmondsKarp算法,也不能直接用不加優化的Danic算法,這樣會TLE7個點。
本題正解是Dinic算法加上當前弧優化。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #include<cstring>
 6 #include<cstdlib>
 7 inline int getint() {
8 char ch; 9 while(!isdigit(ch=getchar())); 10 int x=ch^0; 11 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0); 12 return x; 13 } 14 const int inf=0x7fffffff; 15 int s,t; 16 struct Edge { 17 int from,to; 18 bool remain; 19 }; 20 const int E=1400000
,V=400002; 21 Edge e[E]; 22 std::vector<int> g[V]; 23 int sz=0; 24 inline void add_edge(const int u,const int v,const bool w) { 25 e[sz]=(Edge){u,v,w}; 26 g[u].push_back(sz); 27 sz++; 28 } 29 int d[V]; 30 inline void SPFA() { 31 d[s]=0; 32 for(register int i=1;i<=t;i++) d[i]=inf;
33 std::queue<int> q; 34 q.push(s); 35 while(!q.empty()) { 36 int x=q.front(); 37 q.pop(); 38 if(x==t) return; 39 for(register unsigned i=0;i<g[x].size();i++) { 40 Edge &y=e[g[x][i]]; 41 if((d[x]+1<d[y.to])&&y.remain) { 42 d[y.to]=d[x]+1; 43 q.push(y.to); 44 } 45 } 46 } 47 } 48 unsigned cur[V]; 49 bool Augment(const int x,const bool remain) { 50 if(x==t) return remain; 51 for(unsigned &i=cur[x];i<g[x].size();i++) { 52 Edge &y=e[g[x][i]]; 53 if((d[y.to]>d[x])&&y.remain) { 54 if(Augment(y.to,std::min(remain,y.remain))) { 55 e[g[x][i]].remain^=true; 56 e[g[x][i]^1].remain^=true; 57 return true; 58 } 59 } 60 } 61 return false; 62 } 63 inline int Dinic() { 64 int maxflow=0; 65 for(SPFA();d[t]!=inf;SPFA()) { 66 memset(cur,0,sizeof cur); 67 while(Augment(s,true)) maxflow++; 68 } 69 return maxflow; 70 } 71 int main() { 72 int n2=getint(),n1=getint(),n3=getint(); 73 s=0,t=n1+n2*2+n3+1; 74 for(register int i=1;i<=n1;i++) { 75 add_edge(s,i,true); 76 add_edge(i,s,false); 77 } 78 for(register int m=getint();m;m--) { 79 int a=getint(),b=getint(); 80 add_edge(b,n1+a,true); 81 add_edge(n1+a,b,false); 82 } 83 for(register int i=1;i<=n2;i++) { 84 add_edge(n1+i,n1+n2+i,true); 85 add_edge(n1+n2+i,n1+i,false); 86 } 87 for(register int m=getint();m;m--) { 88 int a=getint(),b=getint(); 89 add_edge(n1+n2+a,n1+n2*2+b,true); 90 add_edge(n1+n2*2+b,n1+n2+a,false); 91 } 92 for(register int i=1;i<=n3;i++) { 93 add_edge(n1+n2*2+i,t,true); 94 add_edge(t,n1+n2*2+i,false); 95 } 96 printf("%d\n",Dinic()); 97 return 0; 98 }

[洛谷1231]教輔的組成