题目:BZOJ1458. 题目:有一个 n ∗ m n*m n∗m的矩阵,有 k k k个位置不能填.现在限制第 i i i行至少填 C i C_i Ci格,第 i i i列至少填 L i L_i Li格,判定是否可以满足条件,并在满足条件时输出最少需要填的格子数. 1 ≤ n , m ≤ 100 1\leq n,m\leq 100 1≤n,m≤100.
首先判定很容易,我们只考虑如何填最少的格子.
当然可以上下界网络流做,不过感觉上下界有些大材小用了.
考虑先把所有可以填的格子填上,我们记填入的数量为 s u m sum sum;然后考虑去掉最多的格子,记去掉的格子数量为 m x mx mx,那么答案就是 s u m − m x sum-mx sum−mx.
显然 s u m sum sum是很好求的,考虑如何求 m x mx mx.
考虑对每行建一个点,由源点往每个点连一条边,流量为这一行可以去掉格子的最大数量(将那些不能填的格子也考虑进去);对每列建一个点,每个点向汇点连一条边,流量为这一列可以去掉格子的最大数量;若某个位置上的点 ( i , j ) (i,j) (i,j)可以填,则由第 i i i行向第 j j j列连一条流量为 1 1 1的边.最后跑一个最大流就是 m x mx mx.
代码如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=100,INF=(1<<30)-1; int n,m,sk,a[2][N+9],b[N+9][N+9],st,td; struct side{ int y,next,f; }e[N*(N+2)*2+9]; int lin[N*2+9],cs; void Ins(int x,int y,int v){e[++cs].y=y;e[cs].f=v;e[cs].next=lin[x];lin[x]=cs;} queue<int>q; int dis[N*2+9]; bool Bfs_div(int st,int td){ for (int i=1;i<=n;++i) dis[i]=0; dis[st]=1;q.push(st); while (!q.empty()){ int t=q.front();q.pop(); for (int i=lin[t];i;i=e[i].next) if (!dis[e[i].y]&&e[i].f) dis[e[i].y]=dis[t]+1,q.push(e[i].y); } return dis[td]; } int cur[N*2+9]; int Dfs_path(int k,int td,int flow){ if (k==td) return flow; int res=0; for (int &i=cur[k];i;i=e[i].next) if (dis[k]+1==dis[e[i].y]&&e[i].f){ int t=Dfs_path(e[i].y,td,min(flow,e[i].f)); flow-=t;res+=t; e[i].f-=t;e[i^1].f+=t; if (!flow) return res; } return res; } int Max_flow(int st,int td){ int res=0; for (;Bfs_div(st,td);res+=Dfs_path(st,td,INF)) for (int i=1;i<=n;++i) cur[i]=lin[i]; return res; } int ans,sum; Abigail into(){ scanf("%d%d%d",&n,&m,&sk); for (int i=1;i<=n;++i){ scanf("%d",&a[0][i]); a[0][i]=m-a[0][i]; } for (int i=1;i<=m;++i){ scanf("%d",&a[1][i]); a[1][i]=n-a[1][i]; } sum+=n*m; for (int i=1;i<=sk;++i){ int x,y; scanf("%d%d",&x,&y); if (!b[x][y]) --a[0][x],--a[1][y],--sum; if (a[0][x]<0||a[1][y]<0) ans=-1; b[x][y]=1; } } Abigail work(){ if (ans<0) return; cs=1; for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) if (!b[i][j]) Ins(i,j+n,1),Ins(j+n,i,0); st=n+m+1; for (int i=1;i<=n;++i) Ins(st,i,a[0][i]),Ins(i,st,0); td=n+m+2; for (int i=1;i<=m;++i) Ins(i+n,td,a[1][i]),Ins(td,i+n,0); n=td; ans=sum-Max_flow(st,td); } Abigail outo(){ ans<0?puts("JIONG!"):printf("%d\n",ans); } int main(){ into(); work(); outo(); return 0; }