NOI赛前训练——专项测试1·网络流
Posted troywar
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOI赛前训练——专项测试1·网络流相关的知识,希望对你有一定的参考价值。
T1:
题目大意:
给一个长度为$n(n<=200)$的数列$h$,再给$m$个可以无限使用的操作,第$i$个操作为给长度为花费$c_i$的价值给长度为$l_i$的数列子序列+1或-1,求将数列变为不下降数列的最小花费。
题解:
第一部分(上下界最小费用可行流):
设$h_0=-inf,h_{n+1}=inf$,令$a$为$h$的差分数组,即$a_i=h_{i}-h_{i-1}$。考虑当对于区间$[l,r]$操作时(比如+1),相当于$a_{r+1}$减少1,$a_{l}$增加1。若将$a$数组看做点集,这个变化相当于从$r+1$到$l$的一条流量为$1$的有向边,反之(-1)亦然。
显然问题相当于把$a$数组元素均变为 不为0。那么我们由S向$a_{i}>0$的位置连$flow=[0,a_{i}],cost=0$的边,表示${i}$可以减少流量上下界,对于$a_{i}<0$的位置,我们至少要使其增加$-a_i$所以我们向$T$连$flow=[-a_i,inf],cost=0$的边。对于每个操作我们由于可无限使用我们就给所有合法位置连$flow=[0,inf],cost=c_{i}$的边,然后我们可以跑一个上下界解决问题。
等等,这样的确解决了问题,不过我们观察一下这个图,会发现上下界源点只连向了$T$,而上下界汇点只被那些$a_{i}<0$的点连接到。
我们把这个图转化一下,会发现对于上面的建图方式,我们只把$a_{i}<0$的边建成$flow=-a_i,cost=0$的边即可,根本不需要跑上下界。这就是另外一种思考方式。
第二部分(最小费用最大流):
我们考虑那些$a_{i}<0$的点变为$0$一定比使其变为任一整数更优秀,同时这也是我们的判断有没有解的依据。
所以我们就直接由$a_{i}<0$的点连向$T$的边为$flow=-a_i,cost=0$即可,如果所有连向$T$的边都流满,说明有解,同时由于上述性质,一定是最优解。
不过这两个时间复杂度并没有太大区别。
代码:
1 #include "bits/stdc++.h" 2 3 using namespace std; 4 5 #define inf 0x3f3f3f3f 6 7 inline int read() { 8 int s=0,k=1;char ch=getchar (); 9 while (ch<‘0‘|ch>‘9‘) ch==‘-‘?k=-1:0,ch=getchar(); 10 while (ch>47&ch<=‘9‘) s=s*10+(ch^48),ch=getchar(); 11 return s*k; 12 } 13 14 const int N=1e3+10; 15 16 struct edges { 17 int v,cap,cost;edges *pair,*last; 18 }edge[N*N],*head[N];int cnt; 19 20 inline void push(int u,int v,int cap,int cost) { 21 edge[++cnt]=(edges){v,cap,cost,edge+cnt+1,head[u]},head[u]=edge+cnt; 22 edge[++cnt]=(edges){u,0,-cost,edge+cnt-1,head[v]},head[v]=edge+cnt; 23 } 24 25 int S,T,ss,tt,n,fl,m; 26 int piS,vis[N]; 27 long long cost; 28 29 inline int aug(int x,int w) { 30 if (x==T) return cost+=1ll*piS*w,fl+=w,w; 31 vis[x]=true; 32 int ret=0; 33 for (edges *i=head[x];i;i=i->last) 34 if (i->cap&&!i->cost&&!vis[i->v]) { 35 int flow=aug(i->v,min(i->cap,w)); 36 i->cap-=flow,i->pair->cap+=flow,ret+=flow,w-=flow; 37 if (!w) break; 38 } 39 return ret; 40 } 41 42 inline bool modlabel() { 43 static int d[N]; 44 memset(d,0x3f,sizeof d);d[T]=0; 45 static deque<int> q;q.push_back(T); 46 int dt; 47 while (!q.empty()) { 48 int x=q.front();q.pop_front(); 49 for (edges *i=head[x];i;i=i->last) 50 if (i->pair->cap&&(dt=d[x]-i->cost)<d[i->v]) 51 (d[i->v]=dt)<=d[q.size()?q.front():0] 52 ?q.push_front(i->v):q.push_back(i->v); 53 } 54 for (int i=S;i<=T;++i) 55 for (edges *j=head[i];j;j=j->last) 56 j->cost+=d[j->v]-d[i]; 57 piS+=d[S]; 58 return d[S]<inf; 59 } 60 61 inline void solve() { 62 piS = cost = 0; 63 while(modlabel()) 64 do memset(vis,0,sizeof vis); 65 while(aug(S, inf)); 66 } 67 68 int h[N],a[N],c[N],l[N],typ[N]; 69 int f[N],g[N]; 70 71 int main(){ 72 n=read(),m=read(); 73 for (int i=1;i<=n;++i) 74 h[i]=read(); 75 for (int i=n;i>1;--i) 76 h[i]=h[i]-h[i-1]; 77 h[1]=inf,h[n+1]=inf; 78 ss=n+2,tt=ss+1,T=tt+1; 79 char opt[2]; 80 for (int i=1;i<=m;++i) { 81 scanf("%s",opt),l[i]=read(),c[i]=read(); 82 typ[i]=opt[0]==‘+‘; 83 } 84 ++n; 85 for (int i=1;i<=n;++i) 86 if (h[i] > 0) 87 push(ss,i,h[i],0); 88 else if(h[i]<0) push(i,tt,inf,0),a[i]=-h[i],a[tt]+=h[i],push(i,T,a[i],0); 89 push(tt,ss,inf,0); 90 push(S,tt,-a[tt],0); 91 memset(f,0x3f,sizeof(f)); 92 f[0]=0; 93 memcpy(g,f,sizeof g); 94 for (int j=1;j<=m;++j) 95 for (int k=l[j];k<=n;k+=l[j]) 96 if(typ[j]) 97 for (int i=n-1;i>=l[j];--i) 98 f[i]=min(f[i],f[i-l[j]]+c[j]); 99 else 100 for (int i=n-1;i>=l[j];--i) 101 g[i]=min(g[i],g[i-l[j]]+c[j]); 102 // puts() 103 for (int j=1;j<=m;++j) 104 if (typ[j]){ 105 if (f[l[j]]==c[j]) 106 for (int i=l[j]+1;i<=n;++i) 107 push(i,i-l[j],inf,c[j]); 108 }else 109 if (g[l[j]]==c[j]) 110 for (int i=1;i+l[j]<=n;++i) 111 push(i,i+l[j],inf,c[j]); 112 solve(); 113 if (fl==-a[tt]) 114 printf("%lld\n",cost); 115 else puts("-1"); 116 }
1 #include "bits/stdc++.h" 2 3 using namespace std; 4 5 #define inf 0x3f3f3f3f 6 7 inline int read() { 8 int s=0,k=1;char ch=getchar (); 9 while (ch<‘0‘|ch>‘9‘) ch==‘-‘?k=-1:0,ch=getchar(); 10 while (ch>47&ch<=‘9‘) s=s*10+(ch^48),ch=getchar(); 11 return s*k; 12 } 13 14 const int N=1e3+10; 15 16 struct edges { 17 int v,cap,cost;edges *pair,*last; 18 }edge[N*N],*head[N];int cnt; 19 20 inline void push(int u,int v,int cap,int cost) { 21 edge[++cnt]=(edges){v,cap,cost,edge+cnt+1,head[u]},head[u]=edge+cnt; 22 edge[++cnt]=(edges){u,0,-cost,edge+cnt-1,head[v]},head[v]=edge+cnt; 23 } 24 25 int S,T,ss,tt,n,fl,m; 26 int piS,vis[N]; 27 long long cost; 28 29 inline int aug(int x,int w) { 30 if (x==T) return cost+=1ll*piS*w,fl+=w,w; 31 vis[x]=true; 32 int ret=0; 33 for (edges *i=head[x];i;i=i->last) 34 if (i->cap&&!i->cost&&!vis[i->v]) { 35 int flow=aug(i->v,min(i->cap,w)); 36 i->cap-=flow,i->pair->cap+=flow,ret+=flow,w-=flow; 37 if (!w) break; 38 } 39 return ret; 40 } 41 42 inline bool modlabel() { 43 static int d[N]; 44 memset(d,0x3f,sizeof d);d[T]=0; 45 static deque<int> q;q.push_back(T); 46 int dt; 47 while (!q.empty()) { 48 int x=q.front();q.pop_front(); 49 for (edges *i=head[x];i;i=i->last) 50 if (i->pair->cap&&(dt=d[x]-i->cost)<d[i->v]) 51 (d[i->v]=dt)<=d[q.size()?q.front():0] 52 ?q.push_front(i->v):q.push_back(i->v); 53 } 54 for (int i=S;i<=T;++i) 55 for (edges *j=head[i];j;j=j->last) 56 j->cost+=d[j->v]-d[i]; 57 piS+=d[S]; 58 return d[S]<inf; 59 } 60 61 inline void solve() { 62 piS = cost = 0; 63 while(modlabel()) 64 do memset(vis,0,sizeof vis); 65 while(aug(S, inf)); 66 } 67 68 int h[N],a[N],c[N],l[N],typ[N]; 69 int f[N],g[N]; 70 71 int main(){ 72 n=read(),m=read(); 73 for (int i=1;i<=n;++i) 74 h[i]=read(); 75 for (int i=n;i>1;--i) 76 h[i]=h[i]-h[i-1]; 77 h[1]=inf,h[n+1]=inf; 78 // ss=n+2,tt=ss+1,T=tt+1; 79 char opt[2]; 80 for (int i=1;i<=m;++i) { 81 scanf("%s",opt),l[i]=read(),c[i]=read(); 82 typ[i]=opt[0]==‘+‘; 83 } 84 ++n;T=n+1; 85 for (int i=1;i<=n;++i) 86 if (h[i] > 0) 87 push(S,i,h[i],0); 88 else if(h[i]<0) push(i,T,-h[i],0),a[tt]+=h[i];//,push(i,T,a[i],0); 89 // push(tt,ss,inf,0); 90 // push(S,tt,-a[tt],0); 91 memset(f,0x3f,sizeof(f)); 92 f[0]=0; 93 memcpy(g,f,sizeof g); 94 for (int j=1;j<=m;++j) 95 for (int k=l[j];k<=n;k+=l[j]) 96 if(typ[j]) 97 for (int i=n-1;i>=l[j];--i) 98 f[i]=min(f[i],f[i-l[j]]+c[j]); 99 else 100 for (int i=n-1;i>=l[j];--i) 101 g[i]=min(g[i],g[i-l[j]]+c[j]); 102 for (int j=1;j<=m;++j) 103 if (typ[j]){ 104 if (f[l[j]]==c[j]) 105 for (int i=l[j]+1;i<=n;++i) 106 push(i,i-l[j],inf,c[j]); 107 }else 108 if (g[l[j]]==c[j]) 109 for (int i=1;i+l[j]<=n;++i) 110 push(i,i+l[j],inf,c[j]); 111 solve(); 112 // printf("%d %d\n",fl); 113 if (fl==-a[tt]) 114 printf("%lld\n",cost); 115 else puts("-1"); 116 }
T2:
题目大意:
emmm,由于并没在网上找到这题,题意我就不发了,仅供自己记忆233。
题解:
这是一道及其简单的模拟网络流最小割的静态仙人掌。(完全不需要题意……各位就知道了)
没什么好说的……
tajan缩点,树剖+线段树维护,以及8k代码。没了。
代码:
1 #include "bits/stdc++.h" 2 3 inline int read(){ 4 int s=0,k=1;char ch=getchar(); 5 while (ch<‘0‘|ch>‘9‘) ch==‘-‘?k=-1:0,ch=getchar(); 6 while (ch>47&ch<=‘9‘) s=s*10+(ch^48),ch=getchar(); 7 return s*k; 8 } 9 10 using namespace std; 11 12 #define inf 0x7fffffff 13 14 const int N=5e5+10,M=1e6+10; 15 16 struct node { 17 int a,b,w,id; 18 }line[N]; 19 20 struct edges{ 21 int v,w;edges *last;node *id; 22 }edge[N<<1],*head[N];int cnt=1; 23 24 inline void push(int u,int v,int w){ 25 edge[++cnt]=(edges) {v,w,head[u]},head[u]=edge+cnt; 26 } 27 28 int bccno[N],bcc_cnt,low[N],dfn[N],idx,stk[N],top,size[N],aa[N]; 29 bool vis[N],used[N]; 30 31 inline void tarjan(int x,int fa) { 32 low[x]=dfn[x]=++idx; 33 stk[++top]=x; 34 for (edges *i=head[x];i;i=i->last) if(i->v!=fa) { 35 if(!dfn[i->v]) 36 tarjan(i->v,x), 37 low[x]=min(low[x],low[i->v]); 38 else low[x]=min(low[x],dfn[i->v]); 39 } 40 if(dfn[fa]<low[x]) { 41 bcc_cnt++;int t; 42 do t=stk[top--],bccno[t]=bcc_cnt,++size[bcc_cnt];while (t!=x); 43 } 44 } 45 46 struct Tree { 47 int val; 48 Tree *lc,*rc; 49 inline void update() { 50 val=min(lc->val,rc->val); 51 } 52 }tree[N<<3];int cnt_tree; 53 54 struct Segment{ 55 Tree *root; 56 57 inline void build(Tree *&u,int l,int r) { 58 if(!u) u=tree+cnt_tree,cnt_tree++; 59 if(l==r) return void(u->val=aa[l]); 60 int mid=l+r>>1; 61 build(u->lc,l,mid); 62 build(u->rc,mid+1,r); 63 u->update(); 64 } 65 66 inline void change(Tree *u,int l,int r,int x,int val){ 67 if(l==r) return void(u->val=val); 68 int mid=l+r>>1; 69 if (x>mid) change(u->rc,mid+1,r,x,val); 70 else change(u->lc,l,mid,x,val); 71 u->update(); 72 } 73 74 inline int query(Tree *u,int l,int r,int x,int y) { 75 if (x>y) return inf; 76 if(x<=l&&r<=y) return u->val; 77 int mid=l+r>>1,ret=0x7fffffff; 78 if (y>mid) ret=query(u->rc,mid+1,r,x,y); 79 if(x<=mid) ret=min(ret,query(u->lc,l,mid,x,y)); 80 return ret; 81 } 82 }seg[N],rt,sft; 83 84 int n,m,pos[N]; 85 vector<int> bcc[N],val[N]; 86 87 inline void dfs(int x) { 88 vis[x]=true; 89 bcc[bccno[x]].push_back(x); 90 pos[x]=bcc[bccno[x]].size(); 91 for (edges *i=head[x];i;i=i->last) { 92 if (!vis[i->v]&&bccno[x]==bccno[i->v]){ 93 i->id->id=pos[x],val[bccno[x]].push_back(i->w),used[i-edge]=used[(i-edge)^1]=true; 94 dfs(i->v); 95 } 96 } 97 if(pos[x]==size[bccno[x]]) 98 for (edges *i=head[x];i;i=i->last) if (!used[i-edge]&&bcc[bccno[x]][0]==i->v) 99 i->id->id=pos[x],val[bccno[x]].push_back(i->w); 100 } 101 102 int heavy[N],sz[N],fat[N],gra[N],deep[N],tid[N],rid[N],up[N],down[N],upb[N]; 103 104 inline void dfs(int x,int fa){ 105 sz[x]=1; 106 for (edges *i=head[x];i;i=i->last) if(i->v!=fa){ 107 deep[i->v]=deep[x]+1,dfs(i->v,x); 108 sz[x]+=sz[i->v]; 109 if (sz[heavy[x]]<sz[i->v]) 110 heavy[x]=i->v; 111 } 112 fat[x]=fa; 113 } 114 115 inline void dfs(int x,int fa,int gr) { 116 gra[x]=gr; 117 tid[x]=++tid[0]; 118 rid[tid[0]]=x; 119 120 if (heavy[x]) { 121 dfs(heavy[x],x,gr); 122 for (edges *i=head[x];i;i=i->last) if (i->v!=fa&&i->v!=heavy[x]) 123 dfs(i->v,x,i->v); 124 for (edges *i=head[x];i;i=i->last) if (i->v!=fa) 125 aa[tid[i->v]]=i->w; 126 } 127 } 128 129 inline int query(int x,int l,int r){ 130 if (l==r) return inf; 131 if (l>r) swap(l,r); 132 return seg[x].query(seg[x].root,1,size[x],l,r-1)+ 133 min(seg[x].query(seg[x].root,1,size[x],r,n), 134 seg[x].query(seg[x].root,1,size[x],1,l-1)) ; 135 } 136 137 inline void sdfs(int x) { 138 for (edges *i=head[x];i;i=i->last) if(i->v!=fat[x]){ 139 up[i->v]=deep[bccno[i->id->a]]>deep[bccno[i->id->b]]?i->id->a:i->id->b; 140 upb[i->v]=i->id->a^i->id->b^up[i->v]; 141 sdfs(i->v); 142 if (i->v==heavy[x]) 143 down[x]=deep[bccno[i->id->a]]<deep[bccno[i->id->b]]?i->id->a:i->id->b; 144 if (i->v==heavy[x]&&fat[x]) { 145 int l=pos[up[x]],r=pos[down[x]]; 146 aa[tid[x]]=query(x,l,r); 147 } 148 } 149 } 150 151 inline void change(int id,int f) { 152 int a=line[id].a,b=line[id].b; 153 if (bccno[a]^bccno[b]) { 154 a=bccno[a],b=bccno[b]; 155 if (deep[a]<deep[b]) swap(a,b); 156 rt.change(rt.root,1,bcc_cnt,tid[a],f); 157 }else { 158 b=bccno[a]; 159 seg[b].change(seg[b].root,1,size[b],line[id].id,f); 160 if (up[b]&&down[b]) { 161 int l=pos[up[b]],r=pos[down[b]],val=query(b,l,r); 162 sft.change(sft.root,1,bcc_cnt,tid[b],val); 163 } 164 } 165 } 166 167 inline int query (int x,int y){ 168 int ret=inf; 169 if (bccno[x]==bccno[y]) { 170 int l=pos[x],r=pos[y]; 171 return query(bccno[x],l,r); 172 } 173 int a=x,b=y; 174 x=bccno[x],y=bccno[y]; 175 while (gra[x]!=gra[y]) { 176 if (deep[gra[x]]<deep[gra[y]]) swap(x,y),swap(a,b); 177 ret=min(ret,rt.query(rt.root,1,bcc_cnt,tid[gra[x]],tid[x])); 178 int l,r; 179 l=pos[a],r=pos[up[x]]; 180 ret=min(ret,query(x,l,r)); 181 a=upb[gra[x]]; 182 if (gra[fat[x]]==gra[x]) { 183 x=fat[x]; 184 ret=min(ret,sft.query(sft.root,1,bcc_cnt,tid[gra[x]],tid[x])); 185 } 186 x=fat[gra[x]]; 187 } 188 if (deep[x]>deep[y]) swap(x,y),swap(a,b); 189 if (x^y) { 190 ret=min(ret,rt.query(rt.root,1,bcc_cnt,tid[x]+1,tid[y])); 191 int l=pos[b],r=pos[up[y]]; 192 ret=min(ret,query(y,l,r)); 193 ret=min(ret,sft.query(sft.root,1,bcc_cnt,tid[x]+1,tid[y]-1)); 194 l=pos[a],r=pos[down[x]]; 195 ret=min(ret,query(x,l,r)); 196 }else 197 ret=min(ret,query(x,pos[a],pos[b])); 198 return ret; 199 } 200 201 int main(){ 202 n=read(),m=read(); 203 for (int i=1;i<=m;++i) { 204 int a=read(),b=read(),w=read(); 205 line[i]=(node){a,b,w}; 206 push(a,b,w),push(b,a,w); 207 edge[cnt].id=edge[cnt-1].id=line+i; 208 } 209 tarjan(1,0); 210 for (int i=1;i<=n;++i) 211 if(!vis[i]) dfs(i); 212 213 for (int i=1;i<=bcc_cnt;++i) { 214 if (size[i]==1) val[i].push_back(inf); 215 for (int j=1;j<=size[i];++j) 216 aa[j]=val[i][j-1]; 217 seg[i].build(seg[i].root,1,size[i]); 218 } 219 memset(head,0,sizeof(head)); 220 cnt=0; 221 for (int i=1;i<=m;++i) { 222 int a,b,w=line[i].w; 223 if ((a=bccno[line[i].a])!=(b=bccno[line[i].b])) 224 push(a,b,w),push(b,a,w),edge[cnt].id=edge[cnt-1].id=line+i; 225 } 226 dfs(1,0); 227 dfs(1,0,1); 228 aa[1]=0; 229 rt.build(rt.root,1,bcc_cnt); 230 memset(aa,127,sizeof aa); 231 232 int Q=read(),typ,a,b; 233 sdfs(1); 234 sft.build(sft.root,1,bcc_cnt); 235 while (Q--) { 236 typ=read(),a=read(),b=read(); 237 if (typ) change(a,b); 238 else printf("%d\n",query(a,b)); 239 } 240 }
T3
题目大意:
$n*n$的棋盘,有一些位置可以放棋子,有一些已经放了棋子,有一些什么都没有,也不能放,要求放置以后满足:第i行和第i列的棋子数相同,同时每行的棋子数占总数比例小于$\frac{A}{B}$。求最多可以放多少,无解则输出$impossible$。
题解:
Orz一发大佬——传送门。
先把整张图放满,题目就转化为最少删多少点就合法。
我们用$numx$来记录每行可以放的和已经放棋子总数,$numy$记录每列。从$S$向第i行连流量为$numx_i$的0费用边,从第j列向$T$连流量为$numy_j$的边。先不考虑怎么构建中间的图,在不考虑$\frac{A}{B}$的情况,我们需要判断流量合法的,我们可以让到$T$的边都满流意味着选了和没选的可以构成全集。
我们对于可以放棋子的地方$(x,y)$,由第$x$行到第$y$列连$flow=1,cost=1$的边,表示将这个点删去的所需价值。
考虑后一个限制。
我们可以枚举每一行最多放置的棋子个数$f$,然后我们从第$i$行向第$i$列连一条$flow=f,cost=0$的边。表示第i行选了最多保留$f$个棋子,第$i$列保留棋子等同于这条边的流量,因为其他连向第$i$列的边都是要费用的,对第$i$行来讲其他的出边也是要费用的,而那些要费用的边就是删去的集合。
然后判断一下当前解是否合法即可。
代码:
1 #include "bits/stdc++.h" 2 3 using namespace std; 4 5 #define inf 0x3f3f3f3f 6 7 inline int read() { 8 int s=0,k=1;char ch=getchar (); 9 while (ch<‘0‘|ch>‘9‘) ch==‘-‘?k=-1:0,ch=getchar(); 10 while (ch>47&ch<=‘9‘) s=s*10+(ch^48),ch=getchar(); 11 return s*k; 12 } 13 14 const int N=100; 15 16 struct edges { 17 int v,cap,cost;edges *pair,*last; 18 }edge[N*N],*head[N];int cnt; 19 20 inline void push(int u,int v,int cap,int cost) { 21 edge[++cnt]=(edges){v,cap,cost,edge+cnt+1,head[u]},head[u]=edge+cnt; 22 edge[++cnt]=(edges){u,0,-cost,edge+cnt-1,head[v]},head[v]=edge+cnt; 23 } 24 25 int S,T,n,fl,ans; 26 int piS,vis[N]; 27 int cost; 28 29 inline int aug(int x,int w) { 30 if (x==T) return cost+=1ll*piS*w,fl+=w,w; 31 vis[x]=true; 32 int ret=0; 33 for (edges *i=head[x];i;i=i->last) 34 if (i->cap&&!i->cost&&!vis[i->v]) { 35 int flow=aug(i->v,min(i->cap,w)); 36 i->cap-=flow,i->pair->cap+=flow,ret+=flow,w-=flow; 37 if (!w) break; 38 } 39 return ret; 40 } 41 42 inline bool modlabel() { 43 static int d[N]; 44 memset(d,0x3f,sizeof d);d[T]=0; 45 static deque<int> q;q.push_back(T); 46 int dt; 47 while (!q.empty()) { 48 int x=q.front();q.pop_front(); 49 for (edges *i=head[x];i;i=i->last) 50 if (i->pair->cap&&(dt=d[x]-i->cost)<d[i->v]) 51 (d[i->v]=dt)<=d[q.size()?q.front():0] 52 ?q.push_front(i->v):q.push_back(i->v); 53 } 54 for (int i=S;i<=T;++i) 55 for (edges *j=head[i];j;j=j->last) 56 j->cost+=d[j->v]-d[i]; 57 piS+=d[S]; 58 return d[S]<inf; 59 } 60 61 inline void solve() { 62 piS = cost = 0; 63 while(modlabel()) 64 do memset(vis,0,sizeof vis); 65 while(aug(S, inf)); 66 } 67 68 char mp[N][N]; 69 int numx[N],numy[N],A,B; 70 71 int main() { 72 n=read(),A=read(),B=read(); 73 T=n<<1|1; 74 int used=0,sum=0; 75 ans=-1; 76 for (int i=1;i<=n;++i) { 77 scanf("%s",mp[i]+1); 78 for (int j=1;j<=n;++j) 79 if(mp[i][j]==‘C‘||mp[i][j]==‘.‘) { 80 ++sum,++numx[i],++numy[j]; 81 used+=mp[i][j]==‘C‘; 82 } 83 } 84 for (int flow=0;flow<=n;++flow) { 85 memset(head,0,sizeof head); 86 cnt=0;fl=0; 87 for (int i=1;i<=n;++i) { 88 push(S,i,numx[i],0); 89 push(i+n,T,numy[i],0); 90 push(i,i+n,flow,0); 91 for (int j=1;j<=n;++j) 92 if(mp[i][j]==‘.‘) 93 push(i,j+n,1,1); 94 } 95 solve(); 96 if (fl==sum&&flow*B<=(sum-cost)*A) 97 ans=max(ans,sum-cost); 98 } 99 if (ans==-1) puts("impossible"); 100 else printf("%d\n",ans-used); 101 }
以上是关于NOI赛前训练——专项测试1·网络流的主要内容,如果未能解决你的问题,请参考以下文章
hihoCoder 1369 网络流一·Ford-Fulkerson算法 (网络流学习#1 记录)