BZOJ 4808 浅谈精准卡时二分图最大独立集

来源:互联网 发布:运动减肥软件下载 编辑:程序博客网 时间:2024/06/05 14:18

这里写图片描述
世界真的很大
这道题虽然并不是很难,但也算是卡了一下原先的不成熟二分图写法吧
按照自己的理解建的双向边用了这么久的却没有什么问题,但是在这道题上却完美的T掉了。。
无奈只得改成有二分图一侧向另一侧连单向边
不幸啊。。。付阔达

看题先:

description:

众所周知,马后炮是中国象棋中很厉害的一招必杀技。”马走日字”。本来,如果在要去的方向有别的棋子挡住(俗
称”蹩马腿”),则不允许走过去。为了简化问题,我们不考虑这一点。马跟马显然不能在一起打起来,于是rly在
一天再次借来了许多许多的马在棋盘上摆了起来……但这次,他实在没兴趣算方案数了,所以他只想知道在N×M的
矩形方格中摆马使其互不吃到的情况下的最多个数。但是,有一个很不幸的消息,rly由于玩得太Happy,质量本来
就不好的棋盘被rly弄坏了,不过幸好只是破了其中的一些格子(即不能再放子了),问题还是可以继续解决的。

input:

一行,两个正整数N和M。
接下来N行,每行M个数,要么为0,表示没坏,要么为1,表示坏了。
N<=200,M<=200

output:

一行,输出最多的个数。

最多能放多少马。。
两匹马不能共存于一张图上,只有他们各在“日字”的两端
那么就是对于“日”字的两端的点就是“有你没有他”的结构
再考虑到这是一张网格图
二分图的最大独立集。。
不能共存的两个点之间建一条边,最大匹配求最大独立集。

理论上是这样然后就跑匈牙利了
然后完美的T掉
上午写的这道题中午放这玩意儿在机房和网上标程对拍了一中午,没有问题
然后发现极限数据全是0我要跑7秒8秒
犹豫之后,还是改了写法
主要是200的范围4000的点1e6的边,实在是大了一点。。
尽量的缩减边数了

完整代码:

#include<stdio.h>struct edge{    int v,last;}ed[4000010];int n,m,num=0,tot=0,ans=0,cnt=0;int head[100010],book[100010],match[100010],mp[330][330];int fx[8]={2,2,1,-1,-2,-2,1,-1},fy[8]={1,-1,2,2,1,-1,-2,-2};void add(int u,int v){    num++;    ed[num].v=v;    ed[num].last=head[u];    head[u]=num;}inline int dfs(int u){    for(int i=head[u];i;i=ed[i].last)    {        int v=ed[i].v;        if(book[v]!=tot)        {            book[v]=tot;            if(!match[v] || dfs(match[v]))            {                match[v]=u,match[u]=v;                return 1;            }        }    }    return 0;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            scanf("%d",&mp[i][j]),cnt+=(!mp[i][j]);    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)        if((i+j)&1)        {            if(mp[i][j]) continue ;            int S=(i-1)*m+j;            for(int k=0;k<8;k++)            {                int x1=i+fx[k],y1=j+fy[k];                if(x1>=1 && x1<=n && y1>=1 && y1<=m && !mp[x1][y1])                    add(S,(x1-1)*m+y1);            }        }    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)        if((i+j)&1)        {            int S=(i-1)*m+j;            if(mp[i][j]) continue ;            tot++;            if(!match[S]) ans+=dfs(S);        }    printf("%d\n",cnt-ans);    return 0;}/*EL PSY CONGROO*/

嗯,就是这样

阅读全文
0 0