[八省联考2018]劈配
题解:
这题思路就是暴力。。 主要在于分析复杂度?
Dinic跑二分图$msqrt(n)$ 这题好像用不到。。
首先这是个匹配问题显然需要利用网络流
考虑第一问
每一次我们就暴力按照志愿顺序加入边
直到二分图匹配数+1
这个复杂度是$(nm)*nm$的(因为一次只增广一条边所以每次是nm的,不过这个很明显是跑不满而且差挺多的)
这样比较gg,我们注意到有用的边只有C条
大概是$(nm/c)*cn$ 也就是n^2m的(我这个复杂度假设了c相同)
(洛谷上的题解说是$n^2c$的 感觉不太对。。)
考虑第二问
首先肯定要二分答案
然后在残余网络上继续跑(记录n个残余网络)
时间复杂度$nlogn*nc$
总时间复杂度$n^2(clogn+m)$
这题交上去70。。
查错查的心态爆炸
多组数据就炸单组数据就过
然后以为是没清空什么东西。。
后来发现是 还原的时候我的还原顺序不对导致还原了上一次的答案
而由于这个还原不还原也是对的,所以单组数据没炸
***还原的时候要逆序还原
***memset还可以清空自定义类型??
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for(int i=h;i<=t;i++) #define dep(i,t,h) for(int i=t;i>=h;i--) #define ll long long #define me(x) memset(x,0,sizeof(x)) #define mep(x,y) memcpy(x,y,sizeof(y)) #define mid ((h+t+1)>>1) namespace IO{ char ss[1<<24],*A=ss,*B=ss; IL char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T> void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48); while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } char sr[1<<24],z[20]; int Z,C1=-1; template<class T>void wer(T x) { if (x<0) sr[++C1]='-',x=-x; while (z[++Z]=x%10+48,x/=10); while (sr[++C1]=z[Z],--Z); } IL void wer1() { sr[++C1]=' '; } IL void wer2() { sr[++C1]='\n'; } template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;} template<class T>IL void mina(T &x,T y) {if (x>y) x=y;} template<class T>IL T MAX(T x,T y){return x>y?x:y;} template<class T>IL T MIN(T x,T y){return x<y?x:y;} }; using namespace IO; const int INF=1e9; const int N=300; int T,c,n,m,a[N],f[N][N],s,t,se[N],ans[N],ans2[N]; vector<int> ve[N][N]; const int M=450; const int M2=6000; struct re{ int a,b,c,flow; }jl[M2]; int cnt1=0; struct Dinic{ int head[M],head2[M],d[M],l,flow; re e[M2]; IL void arr(int x,int y,int z) { e[++l].a=head[x]; e[l].b=y; e[l].c=z; e[l].flow=0; jl[++cnt1]=(re){x,head[x]}; head[x]=l; } IL void arr2(int x,int y,int z) { arr(x,y,z); arr(y,x,0); } bool bfs() { rep(i,1,t) d[i]=INF; d[s]=0; queue<int> q; q.push(s); while (!q.empty()) { int x=q.front(); q.pop(); for (int u=head[x];u;u=e[u].a) { int v=e[u].b; if (d[v]==INF&&e[u].c>e[u].flow) d[v]=d[x]+1,q.push(v); } } if (d[t]==INF) return(0); else return(1); } int dfs(int x,int y) { if (x==t||!y) return(y); int f,flow=0; for (rint u=head[x];u;u=e[u].a) { int v=e[u].b; if (d[v]==d[x]+1&&(f=dfs(v,MIN(y,e[u].c-e[u].flow)))>0) { flow+=f; y-=f; e[u].flow+=flow; if (u%2==1) e[u+1].flow-=flow; else e[u-1].flow-=flow; } if (!y) break; head[x]=u; } return flow; } void maxflow() { mep(head2,head); while (bfs()) { flow+=dfs(s,INF); mep(head,head2); } } }D[202],now; IL void fz(Dinic &a,Dinic &b) { mep(a.head,b.head); mep(a.e,b.e); a.l=b.l; a.flow=b.flow; } IL bool check(int x,int y) { fz(now,D[y]); rep(i,1,se[x]) { int l=ve[x][i].size(); for (int j=0;j<l;j++) now.arr2(x,ve[x][i][j]+n,1); } now.maxflow(); if (now.flow==D[y].flow+1) return(1); else return(0); } int main() { read(T); read(c); rep(ttt,1,T) { read(n); read(m); rep(i,1,m) read(a[i]); rep(i,1,n) { rep(j,1,m) ve[i][j].clear(); rep(j,1,m) { read(f[i][j]); if (f[i][j]) ve[i][f[i][j]].push_back(j); } } rep(i,1,n) read(se[i]); s=0; t=n+m+1; D[0].l=0; me(D[0].head); rep(i,1,n) D[0].arr2(s,i,1); rep(i,1,m) D[0].arr2(i+n,t,a[i]); rep(i,1,n) { ans[i]=m+1; fz(D[i],D[i-1]); int tmp=D[i].l; cnt1=0; rep(j,1,m) { dep(k,cnt1,1) D[i].head[jl[k].a]=jl[k].b; int l=ve[i][j].size(); D[i].l=tmp; cnt1=0; for (int k=0;k<l;k++) D[i].arr2(i,ve[i][j][k]+n,1); D[i].maxflow(); if (D[i].flow==D[i-1].flow+1) { ans[i]=j; break; } } } rep(i,1,n) { ans2[i]=0; if (ans[i]>se[i]) { int h=0,t=i-1; while (h<t) { if (check(i,mid)) h=mid; else t=mid-1; } if (!check(i,h)) ans2[i]=i; else ans2[i]=i-h-1; } } rep(i,1,n) wer(ans[i]),wer1(); wer2(); rep(i,1,n) wer(ans2[i]),wer1(); wer2(); } fwrite(sr,1,C1+1,stdout); return 0; }