这题是一个裸的网络流的题,但是本蒟蒻还是调试了半天2333.总是犯低级错误。
一开始我是用EK算法实现的。结果如下:

然后我又用Dinic算法实现了一下。

发现更慢了2333.我也不知道为啥,按道理Dinic应该比EK快的不知道到哪里去了才对。
下面是我的代码实现:
EK算法:
#include <bits/stdc++.h>
using namespace std;
#define re register
inline long long read() {
char ch = getchar(); long long x = 0, f = 1;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
} while('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
const int N = 36000,M = 5000000;
struct line {
int v;
int cap;
int nxt;
} datas [M];
int head [N],cnt = 1;
inline void add (int a,int b,int c) {
++ cnt;
datas [cnt].v = b;
datas [cnt].cap = c;
datas [cnt].nxt = head [a];
head [a] = cnt;
}
int s = 0,t;
int n,m;
inline int qlink (int x,int y) {
//前部点
return x * n + y;
}
inline int hlink (int x,int y) { //后部点
return qlink (n,n) + qlink (x,y);
}
int dx [] = {0,0,1,-1},dy [] = {1,-1,0,0};
bool vis [N];
inline int dfs (int u,int flow) {
vis [u] = true;
//开始EK算法
if (u == t) {
return flow;
}
for (int ptr = head [u];ptr;ptr = datas [ptr].nxt) {
int v = datas [ptr].v,c = datas [ptr].cap;
if (!c || vis [v]) {
continue ;
}
int ret = dfs (v,min (flow,c));
if (!ret) {
continue ;
}
//开始减掉自己
datas [ptr].cap -= ret;
datas [ptr ^ 1].cap += ret;
return ret;
}
return 0;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen ("shit.txt","r",stdin);
#endif
#ifdef ONLINE_JUDGE
#endif
n = read (),m = read ();
t = hlink (n,n) + 1;
for (int i = 1;i <= n;++ i) {
for (int j = 1;j <= n;++ j) {
add (qlink (i,j),hlink (i,j),1);
add (hlink (i,j),qlink (i,j),0);
}
}
for (int i = 1;i <= m;++ i) {
int x = read (),y = read ();
//开始连接到源点
add (s,qlink (x,y),1);
add (qlink (x,y),s,0);
}
//开始连接周围的点
for (int i = 1;i <= n;++ i) {
for (int j = 1;j <= n;++ j) {
for (int k = 0;k < 4;++ k) {
int x = i + dx [k],y = j + dy [k];
if (x < 1 || y < 1 || x > n || y > n) {
continue ;
}
add (hlink (i,j),qlink (x,y),1);
add (qlink (x,y),hlink (i,j),0);
}
}
}
//开始连接周围的点
for (int i = 1;i <= n;++ i) {
add (hlink (i,1),t,1);
add (t,hlink (i,1),0);
add (hlink (1,i),t,1);
add (t,hlink (1,i),0);
add (hlink (n,i),t,1);
add (t,hlink (n,i),0);
add (hlink (i,n),t,1);
add (t,hlink (i,n),0);
}
int t = 0;
int ans = 0;
while (t = dfs (s,0x3f3f3f3f)) {
ans += t;
memset (vis,false,sizeof vis);
}
if (ans >= m) {
printf ("YES\n");
}else {
printf ("NO\n");
}
return 0;
}
下面是Dinic算法
#include <bits/stdc++.h>
using namespace std;
#define re register
inline long long read() {
char ch = getchar(); long long x = 0, f = 1;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
} while('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
const int N = 36000,M = 5000000;
struct line {
int v;
int cap;
int nxt;
} datas [M];
int head [N],cnt = 1;
inline void add (int a,int b,int c) {
++ cnt;
datas [cnt].v = b;
datas [cnt].cap = c;
datas [cnt].nxt = head [a];
head [a] = cnt;
}
int s = 0,t;
int n,m;
inline int qlink (int x,int y) {
//前部点
return x * n + y;
}
inline int hlink (int x,int y) { //后部点
return qlink (n,n) + qlink (x,y);
}
int dx [] = {0,0,1,-1},dy [] = {1,-1,0,0};
int d [N];
bool vis [N];
inline bool dinic () {
memset (d,0,sizeof d);
queue<int> q;q.push (s);
d [s] = 1;
while (!q.empty ()) {
int u = q.front ();q.pop ();
for (int ptr = head [u];ptr;ptr = datas [ptr].nxt) {
int v = datas [ptr].v;
if (!d [v] && datas [ptr].cap) {
q.push (v);
d [v] = d [u] + 1;
}
}
}
return d [t];
}
int dfs (int u,int flow) {
if (u == t) {
return flow;
}
int dd = 0;
for (int ptr = head [u];ptr;ptr = datas [ptr].nxt) {
int v = datas [ptr].v,cap = datas [ptr].cap;
if (d [v] == d [u] + 1 && cap) {
int ret = dfs (v,min (cap,flow));
datas [ptr].cap -= ret;
datas [ptr ^ 1].cap += ret;
flow -= ret;
dd += ret;
if (!flow) {
break ;
}
}
}
if (!dd) {
d [u] = -1;
}
return dd;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen ("shit.txt","r",stdin);
#endif
#ifdef ONLINE_JUDGE
#endif
n = read (),m = read ();
t = hlink (n,n) + 1;
for (int i = 1;i <= n;++ i) {
for (int j = 1;j <= n;++ j) {
add (qlink (i,j),hlink (i,j),1);
add (hlink (i,j),qlink (i,j),0);
}
}
for (int i = 1;i <= m;++ i) {
int x = read (),y = read ();
//开始连接到源点
add (s,qlink (x,y),1);
add (qlink (x,y),s,0);
}
//开始连接周围的点
for (int i = 1;i <= n;++ i) {
for (int j = 1;j <= n;++ j) {
for (int k = 0;k < 4;++ k) {
int x = i + dx [k],y = j + dy [k];
if (x < 1 || y < 1 || x > n || y > n) {
continue ;
}
add (hlink (i,j),qlink (x,y),1);
add (qlink (x,y),hlink (i,j),0);
}
}
}
//开始连接周围的点
for (int i = 1;i <= n;++ i) {
add (hlink (i,1),t,1);
add (t,hlink (i,1),0);
add (hlink (1,i),t,1);
add (t,hlink (1,i),0);
add (hlink (n,i),t,1);
add (t,hlink (n,i),0);
add (hlink (i,n),t,1);
add (t,hlink (i,n),0);
}
int t = 0;
int ans = 0;
while (dinic ()) {
ans += dfs (s,0x3f3f3f3f);
}
if (ans >= m) {
printf ("YES\n");
}else {
printf ("NO\n");
}
return 0;
}