关于运行时间

P3355 骑士共存问题

liubw_ @ 2021-11-08 20:55:05

大佬们的代码小于100ms,而同样是网络流的我写的dinic却有极大的常数,跑到了500ms,求优化:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

template <class T>void read(T &x){
    x=0;
    char c,d='0';
    c=getchar();
    while(c<'0'||c>'9'){
        d=c;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    if(d=='-') x=-x;
}
template <class T>void wt(T x){
    if(x/10) wt(x/10);
    putchar(x%10+'0');
}
template <class T>void write_enter(T x){
    if(x<0){
        x=-x;
        putchar('-');
    }
    wt(x);
    putchar('\n');
}
template <class T>void write_space(T x){
    if(x<0){
        x=-x;
        putchar('-');
    }
    wt(x);
    putchar(' ');
}

const int N=205,maxn=0x3f3f3f3f;
int n,head[N*N],cur[N*N],tot=2,s,t;
struct edge{
    int to,nex,cap;
}e[(N*N<<3)+(N*N<<1)];
inline void add(int u,int v,int cap){
    e[tot].nex=head[u];
    head[u]=tot;
    e[tot].to=v;
    e[tot++].cap=cap;
}
inline void addedge(int u,int v,int cap){
    add(u,v,cap);
    add(v,u,0);
}
int dep[N*N];
inline bool bfs(){
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    queue <int> q;
    q.push(s);
    dep[s]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int k=head[u];k;k=e[k].nex){
            int v=e[k].to,cap=e[k].cap;
            if(dep[v]||!cap) continue;
            dep[v]=dep[u]+1;
            q.push(v);
        }
    }
    return dep[t]? 1:0;
}
bool vis[N*N];
inline ll dfs(int u,int f){
    if(u==t||!f) return f;
    int maxf=0,tf;
    vis[u]=1;
    for(int &k=cur[u];k&&f;k=e[k].nex){
        int v=e[k].to,cap=e[k].cap;
        if(dep[v]!=dep[u]+1||!cap) continue;
        tf=dfs(v,min(f,cap));
        f-=tf,maxf+=tf;
        e[k].cap-=tf,e[k^1].cap+=tf;
    }
    return maxf;
}
inline int dinic(){
    int res=0,x;
    while(bfs())
        while((x=dfs(s,maxn))) res+=x;
    return res;
}
#define P(i,j) ((i-1)*n+j)
#define chk(i) (1<=i&&i<=n)
int plux[8]={1,1,2,2,-1,-1,-2,-2},pluy[8]={2,-2,1,-1,2,-2,1,-1};
int numb;
map <tuple<int,int>,bool> mp;
int main(){
    read(n),read(numb);
    for(int i=1;i<=numb;i++){
        int x,y;
        read(x),read(y);
        mp[tie(x,y)]=1;
    }
    s=n*n+1,t=n*n+2;
    int sum=0,pj;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)if(!mp[tie(i,j)]){
            pj=1,sum+=pj;
            if((i+j)%2==0){
                addedge(s,P(i,j),pj);
                for(int opt=0;opt<8;opt++){
                    int x=i+plux[opt],y=j+pluy[opt];
                    if(chk(x)&&chk(y)&&!mp[tie(x,y)]) addedge(P(i,j),P(x,y),maxn);
                }
            }
            else addedge(P(i,j),t,pj);
        }
    write_enter(sum-dinic());
    return 0;
}

by zhiyangfan @ 2021-11-08 21:04:46

不是很清楚这俩优化的效率,反正我会加。

dfs 的时候有两个剪枝。

inline ll dfs(int u,int f){
    if(u==t||!f) return f;
    int maxf=0,tf;
    vis[u]=1;
    for(int &k=cur[u];k&&f;k=e[k].nex){
        int v=e[k].to,cap=e[k].cap;
        if(dep[v]!=dep[u]+1||!cap) continue;
        tf=dfs(v,min(f,cap));
        f-=tf,maxf+=tf;
        e[k].cap-=tf,e[k^1].cap+=tf;
        if (!f) break; //1
    }
    if (!maxf) d[u] = 0; //2
    return maxf;
}

1 处是表示这部分已经榨干了,之后再遍历其他的路没用了。2处类似,只是表示这一个点不能再增广了,之后不访问了。


by zhiyangfan @ 2021-11-08 21:05:26

哦我瞎了,第 1 个优化您加过了qwq(


by KonJAC_xrs @ 2021-11-08 21:13:40

写二分图呗 ~


by KonJAC_xrs @ 2021-11-08 21:14:22

只要用二分图写这道题就能学会卡常,相信我


by liubw_ @ 2021-11-08 21:16:36

@zhiyangfan 感谢!


by liubw_ @ 2021-11-08 21:17:39

@zhiyangfan 虽然但是仍然530ms...


by zhiyangfan @ 2021-11-08 21:20:16

@16岁 qwq 我用您代码卡一下其他部分试试。


by zhiyangfan @ 2021-11-08 21:25:02

@16岁 算了,更慢了qwq

突然发现我的代码跑的也不快,爬了qwq


|