zl程序教程

您现在的位置是:首页 >  其它

当前栏目

[2018.08.07 T1] 签到?

07 T1 签到
2023-09-27 14:28:32 时间

暂无链接

签到?

【问题描述】

这题有毒!
豆豆有一个 n×m n × m 的棋盘,一开始所有的格子都是黑的,可以选择一些黑色的格子把它们变成白色。

豆豆想知道问至少选多少个格子,可以使得每一列满足,该列白格数量 Xi ≥ X i ,每行满足,该行白格数量 Yi ≥ Y i

当然没有这么简单,还有些格子必须是黑色的。

【输入格式】

第一行 n,m,K n , m , K 。分别表示行数、列数、不能选的格子数。

第二行 n n 个数表示Xi

第三行 m m 个数表示Yi

接下来 K K 行,每行两个数描述一个不能选的格子。

【输出格式】

如果要求可以达到,输出一行一个整数表示最少选择的格子。
否则输出“IIllIIll1!”(不含引号)。

【输入样例】

4 4 4
1 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3

【输出样例】

4

【数据范围】

对于 30% 30 % 的数据, 0<n,m10 0 < n , m ≤ 10

对于 100% 100 % 的数据, 0<n,m100,0Knm 0 < n , m ≤ 100 , 0 ≤ K ≤ n m

题解

左边 n n 个点,右边m个点,连 n×m n × m 条边表示每个格子,如果边被流了就表示该格子被选了。

源点向代表行的点连边,容量为 Xi X i ;代表列的点再向汇点连边,容量为 Yi Y i 。但是这样就需要跑有上下界的网络流,实际上可以把网格看成初始为白色的倒着做,就没有下界的限制了。

至于在考场上。。。当然有算法就打啊,有上下界的网络流贼溜。

代码
#include<bits/stdc++.h> 
using namespace std;
const int N=405,M=1e5+5,inf=0x3f3f3f3f;
struct sd{int to,fl;}ed[M];
int id,cnt,ss,tt,s,t,n,m,k,pre,head[N],nxt[M],num[M],d[N],x[N],y[N];
queue<int>dui;
bool GG[N][N];
void added(int f,int t,int w){nxt[++cnt]=head[f],head[f]=cnt,num[cnt]=id;ed[id++]=(sd){t,w};}
void add(int f,int t,int w){added(f,t,w),added(t,f,0);}
bool bfs(int s,int t)
{
    memset(d,0,sizeof(d));
    dui.push(s);d[s]=1;
    int f,to,fl;
    while(!dui.empty())
    {
        f=dui.front();dui.pop();
        for(int i=head[f];i;i=nxt[i])
        {
            to=ed[num[i]].to,fl=ed[num[i]].fl;
            if(d[to]||!fl)continue;
            d[to]=d[f]+1;
            dui.push(to);
        }
    }
    return d[t]; 
}
int dfs(int v,int t,int minn)
{
    if(v==t||!minn)return minn;
    int to,fl,tmp,ans=0;
    for(int i=head[v];i;i=nxt[i])
    {
        to=ed[num[i]].to,fl=ed[num[i]].fl;
        if(d[to]!=d[v]+1||!fl)continue;
        tmp=dfs(to,t,min(minn-ans,fl));
        ed[num[i]].fl-=tmp,ed[num[i]^1].fl+=tmp;
        ans+=tmp;
    }
    return ans;
}
void in()
{
    int a,b,c;
    scanf("%d%d%d",&n,&m,&k);t=n+m+1,ss=400,tt=401;
    add(t,s,inf);
    for(int i=1;i<=n;++i)scanf("%d",&x[i]),add(ss,i,x[i]),add(s,tt,x[i]),add(s,i,inf);
    for(int i=1;i<=m;++i)scanf("%d",&y[i]),add(ss,t,y[i]),add(i+n,tt,y[i]),add(i+n,t,inf);pre=id;
    for(int i=1;i<=k;++i)scanf("%d%d",&a,&b),GG[a][b]=1;
    for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(!GG[i][j])add(i,j+n,1);
}
void ac()
{
    int ans=0;
    while(bfs(ss,tt))dfs(ss,tt,inf);
    for(int i=head[ss];i;i=nxt[i])if(ed[num[i]].fl)puts("IIllIIll1!"),exit(0);
    ed[1].fl=ed[2].fl=0;
    for(int i=head[ss];i;i=nxt[i])ed[num[i]].fl=ed[num[i]^1].fl=0;
    for(int i=head[tt];i;i=nxt[i])ed[num[i]].fl=ed[num[i]^1].fl=0;
    while(bfs(t,s))dfs(t,s,inf);
    for(int i=pre;i<id;i+=2)if(!ed[i].fl)ans++;
    printf("%d",ans);
}
int main(){in();ac();}