关于这题用 ISAP 过不去而 dinic 和匈牙利都能过这件事

P3355 骑士共存问题

donghanwen1225 @ 2022-03-14 22:14:49

RT,这样卡是否有些离谱了……

或者说有没有人能给蒟蒻一点卡常的建议?

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int inf=1<<30;
int fx[8][2]={{2,1},{2,-1},{1,2},{1,-2},{-2,1},{-2,-1},{-1,2},{-1,-2}};
int n,m,x,y,s,t,tot=1,bj[201][201],fir[40005],nxt[1000001],to[1000001],cap[1000001],flow[1000001],pre[40005],h[40005],hsl[40005];
queue<int> q;
int ch(int i,int j){return (i-1)*n+j;}
void ins(int x,int y,int v)
{
    nxt[++tot]=fir[x];
    fir[x]=tot;
    to[tot]=y;
    cap[tot]=v;
}
void seth(int t)
{
    memset(h,-1,sizeof(h));
    q.push(t);h[t]=0;
    while(!q.empty())
    {
        int now=q.front();q.pop();
        hsl[h[now]]++;
        for(int i=fir[now];i;i=nxt[i])
            if(h[to[i]]==-1)
            {
                h[to[i]]=h[now]+1;
                q.push(to[i]);
            }
    }
}
int ISAP(int s,int t)
{
    seth(t);
    int now=s,ans=0,d=1<<30;
    while(h[s]<n*n+2)
    {
        if(now==s) d=1<<30;
        int i=fir[now];
        for(;i;i=nxt[i])
            if(cap[i]>flow[i]&&h[now]==h[to[i]]+1)
            {
                d=min(d,cap[i]-flow[i]);
                now=to[i];pre[to[i]]=i;
                if(now==t)
                {
                    while(now!=s)
                    {
                        int k=pre[now];
                        flow[k]+=d;flow[k^1]-=d;
                        now=to[k^1];
                    }
                    ans+=d;d=1<<30;
                }
                break;
            }
        if(!i)
        {
            if(--hsl[h[now]]==0) break;
            int minh=n*n+1;
            for(int j=fir[now];j;j=nxt[j])
                if(cap[j]>flow[j]) minh=min(minh,h[to[j]]);
            h[now]=minh+1;
            hsl[h[now]]++;
            if(now!=s) now=to[pre[now]^1];
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);s=n*n+1,t=s+1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        bj[x][y]=1;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(bj[i][j]) continue;
            int cur=ch(i,j);
            if((i+j)%2==0)
            {
                ins(s,cur,1),ins(cur,s,0);
                for(int l=0;l<8;l++)
                {
                    int ni=i+fx[l][0],nj=j+fx[l][1],np=ch(ni,nj);
                    if(ni>=1&&nj>=1&&ni<=n&&nj<=n&&!bj[ni][nj])
                        ins(cur,np,inf),ins(np,cur,0);
                }
            }
            else ins(cur,t,1),ins(t,cur,0);
        }
    printf("%d",n*n-m-ISAP(s,t));
    return 0;
}

by hy233 @ 2022-03-14 22:20:57

类二分图dinic和匈牙利跑的快吧(虽然我不会ISAP)

卡dinic的都是毒瘤出题人啊


by 老子是北瓜 @ 2022-03-14 22:23:29

@donghanwen1225 把queue换成手写的,手写的比开O2的STL还快


by donghanwen1225 @ 2022-03-14 22:24:16

srds,卡 ISAP 也很少见吧(

不过蒟蒻写 ISAP 竟然是因为没写过 dinic

不过蒟蒻去写个匈牙利就过了


by donghanwen1225 @ 2022-03-14 22:24:45

@老子是北瓜 谢谢,我去试试


by Icyfires18 @ 2022-03-14 22:24:49

我用isap都过啦呀?


by donghanwen1225 @ 2022-03-14 22:26:28

@Lg_Icyfireyk 请问您能帮我看一下我写的哪里慢了,或者讲一下您是怎么写的吗?


by Icyfires18 @ 2022-03-14 22:27:33

@donghanwen1225 记录


by Icyfires18 @ 2022-03-14 22:35:08

@donghanwen1225 其实我不太了解isap的bfs写法(一直用的dfs的)


by Icyfires18 @ 2022-03-14 22:37:06

@donghanwen1225 可能bfs的比较慢吧,常数上只有cur优化和gap优化


by donghanwen1225 @ 2022-03-14 22:40:01

@Lg_Icyfireyk 实际上我也不太了解 ISAP 的 dfs 写法,所以没看懂您那个类似当前弧优化的 cur 数组是什么道理/kk

我还是写匈牙利吧


| 下一页