liubw_ @ 2021-11-08 20:55:05
大佬们的代码小于100ms,而同样是网络流的我写的
#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