1458: 士兵占领 思路题 最大流

来源:互联网 发布:阿里云可以做ip代理吗 编辑:程序博客网 时间:2024/05/20 07:18

T_T我太弱了这个题都不会做。


反向考虑:
可以把最小问题转化为最大问题:如果把格子填满,我们最多能拿走几个?
这样做法就很显然了。。行列建图就好了。。qwq
有时候脑子需要拐个弯T_T

#include<iostream>#include<cstdio>#include<cstring>#define inf 1000000007using namespace std;int n,m,k,sum,cnt=1,S,T,a[105][105],l[105],c[105],sumx[105],sumy[105];int head[205],cur[205],dis[205],q[205];int next[100005],list[100005],key[100005];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x,int y,int z){    next[++cnt]=head[x];    head[x]=cnt;    list[cnt]=y;    key[cnt]=z;}inline bool BFS(){    memset(dis,-1,sizeof(dis));    dis[S]=1; q[1]=S;    int t=0,w=1,x;    while (t<w)    {        x=q[++t];        for (int i=head[x];i;i=next[i])            if (key[i]&&dis[list[i]]==-1)                 dis[list[i]]=dis[x]+1,q[++w]=list[i];    }    return dis[T]!=-1;}int find(int x,int flow){    if (x==T) return flow;    int w,used=0;    for (int i=cur[x];i;i=next[i])        if (key[i]&&dis[list[i]]==dis[x]+1)        {            w=find(list[i],min(key[i],flow-used));            key[i]-=w; key[i^1]+=w; used+=w;            if (key[i]) cur[x]=i;            if (used==flow) return flow;        }    if (!used) dis[x]=-1;    return used;}inline int dinic(){    int tmp=0;    while (BFS())    {        for (int i=S;i<=T;i++) cur[i]=head[i];        tmp+=find(S,inf);    }    return tmp;}int main(){    n=read(); m=read(); k=read();    for (int i=1;i<=n;i++) l[i]=m-read();    for (int i=1;i<=m;i++) c[i]=n-read();    for (int i=1;i<=k;i++)    {        int x=read(),y=read();        sumx[x]++; sumy[y]++;        a[x][y]=1;        if (sumy[x]>l[x]||sumy[y]>c[y]) {puts("JIONG!"); return 0;}    }    sum=n*m-k; S=0; T=n+m+1;    for (int i=1;i<=n;i++) insert(S,i,l[i]-sumx[i]),insert(i,S,0);    for (int i=1;i<=m;i++) insert(i+n,T,c[i]-sumy[i]),insert(T,i+n,0);    for (int i=1;i<=n;i++)        for (int j=1;j<=m;j++)            if (!a[i][j]) insert(i,j+n,1),insert(j+n,i,0);    cout << sum-dinic() << endl;    return 0;}
0 0