Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<bits/stdc++.h>
- #define fi first
- #define se second
- #define pb push_back
- #define pf push_front
- #define popb pop_back
- #define popf pop_front
- #define ins insert
- #define pq priority_queue
- #define minele min_element
- #define maxele max_element
- #define mp make_pair
- #define lb lower_bound //first pos >= val
- #define ub upper_bound // first pos > val
- #define cnt_bit __builtin_popcount
- #define all(x) x.begin(), x.end()
- #define debug(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
- //#pragma GCC optimize("Ofast")
- //#pragma GCC target("avx,avx2,fma")
- using namespace std;
- mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
- typedef long long ll;
- typedef unsigned long long ull;
- typedef pair<ll, ll> pll;
- typedef pair<int, int> pii;
- int d4x[4] = {1, 0, -1, 0}; int d4y[4] = {0, 1, 0, -1};
- int d8x[8] = {0, 1, 1, 1, 0, -1, -1, -1};
- int d8y[8] = {1, 1, 0, -1, -1, -1, 0, 1};
- int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
- int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
- const int INF = 1e9;
- const ll oo = 1e18;
- const ll maxN = 1e6;
- /* Author : Le Ngoc Bao Anh, 11A5, LQD High School for Gifted Student */
- struct Dinitz {
- struct Edges {
- int u, v;
- ll cap;
- Edges() : u(), v(), cap() {}
- Edges(int _u, int _v, ll _cap) : u(_u), v(_v), cap(_cap) {}
- };
- vector<vector<int>> g;
- vector<Edges> ed;
- vector<int> dist;
- vector<int> id;
- int S, T;
- int n;
- Dinitz() : ed(), n(), S(), T() {}
- Dinitz(int _n, int _S, int _T) {
- n = _n; S = _S; T = _T;
- g.resize(n);
- dist.resize(n);
- id.resize(n);
- for(int i = 0; i < n; i++) g[i].clear();
- ed = vector<Edges>();
- }
- void addEdge(int u, int v, ll cap) {
- g[u].pb((int)ed.size());
- ed.pb(Edges(u, v, cap));
- g[v].pb((int)ed.size());
- ed.pb(Edges(v, u, 0));
- }
- bool bfs() {
- for(int i = 0; i < n; i++) dist[i] = n + 5;
- queue<int> q;
- q.push(S); dist[S] = 0;
- while(!q.empty()) {
- int u = q.front(); q.pop();
- for(int i : g[u]) {
- Edges e = ed[i];
- if(!e.cap) continue;
- if(dist[e.v] <= dist[u] + 1) continue;
- dist[e.v] = dist[u] + 1;
- q.push(e.v);
- }
- }
- return dist[T] < n + 5;
- }
- ll dfs(int u, ll flow) {
- if(u == T || flow == 0) return flow;
- ll ans = 0;
- for(int &i = id[u]; i < (int)g[u].size(); i++) {
- Edges e = ed[g[u][i]];
- if(!e.cap) continue;
- if(dist[e.v] != dist[u] + 1) continue;
- ll f = dfs(e.v, min(flow, e.cap));
- flow -= f;
- ans += f;
- ed[g[u][i]].cap -= f;
- ed[g[u][i] ^ 1].cap += f;
- if(flow == 0) return ans;
- }
- return ans;
- }
- ll Flow() {
- ll ans = 0;
- while(bfs()) {
- for(int i = 0; i < n; i++) id[i] = 0;
- ans += dfs(S, oo);
- }
- return ans;
- }
- vector<pii> getEdge() {
- vector<pii> ans;
- for(int i = 0; i < ed.size(); i++) {
- int u = ed[i].u, v = ed[i].v;
- if(u == S || v == S || u == T || v == T) continue;
- if(!(u & 1)) continue;
- if(!ed[i].cap) ans.pb(make_pair(u, v));
- }
- return ans;
- }
- };
- struct TWOSAT {
- int n;
- vector<vector<int>> g;
- vector<vector<int>> ed;
- vector<int> Num;
- vector<int> Low;
- vector<int> idComp;
- vector<bool> visited;
- stack<int> st;
- vector<int> ord;
- vector<int> idSort;
- int Time, cntComp;
- TWOSAT(int _n = 0) {
- n = _n;
- g.resize(2 * n + 2);
- ed.resize(2 * n + 2);
- Num.resize(2 * n + 2);
- Low.resize(2 * n + 2);
- visited.resize(2 * n + 2);
- idComp.resize(2 * n + 2);
- idSort.resize(2 * n + 2);
- ord.clear();
- Time = cntComp = 0;
- for(int i = 1; i <= 2 * n; i++) {
- g[i].clear(); ed[i].clear();
- idSort[i] = Num[i] = visited[i] = Low[i] = idComp[i] = 0;
- }
- }
- int NOT(int u) {
- return (u > n ? u - n : u + n);
- }
- void Connect(int u, int v) {
- g[u].pb(v);
- }
- void addEdge(int u, int v) {
- // u || v = 1
- Connect(NOT(u), v);
- Connect(NOT(v), u);
- }
- void tarjan(int u) {
- Num[u] = Low[u] = ++Time;
- st.push(u);
- for(auto v : g[u]) {
- if(Num[v]) {
- Low[u] = min(Low[u], Num[v]);
- } else {
- tarjan(v);
- Low[u] = min(Low[u], Low[v]);
- }
- }
- if(Num[u] == Low[u]) {
- int v = 0;
- ++cntComp;
- do {
- v = st.top(); st.pop();
- idComp[v] = cntComp;
- Num[v] = Low[v] = INF;
- } while(v != u);
- }
- }
- void topo(int u) {
- visited[u] = true;
- for(auto v : ed[u]) {
- if(!visited[v]) topo(v);
- }
- ord.pb(u);
- }
- vector<int> do2SAT() {
- for(int i = 1; i <= 2 * n; i++) {
- if(!Num[i]) tarjan(i);
- }
- for(int i = 1; i <= n; i++) {
- if(idComp[i] == idComp[i + n]) return {-1};
- }
- vector<int> ans;
- for(int i = 1; i <= 2 * n; i++) {
- int u = idComp[i];
- for(auto v : g[i]) {
- v = idComp[v];
- if(u == v) continue;
- ed[u].pb(v);
- }
- }
- for(int i = 1; i <= 2 * n; i++) {
- if(!visited[i]) topo(i);
- }
- reverse(all(ord));
- for(int i = 0; i < 2 * n; i++) idSort[ord[i]] = i + 1;
- for(int i = 1; i <= n; i++) {
- int u = idComp[i], v = idComp[i + n];
- if(idSort[u] > idSort[v]) ans.pb(i);
- }
- return ans;
- }
- };
- const int N = 105;
- bool banned[N][N];
- bool ok[N * N];
- void solve() {
- int n, m, k; cin >> n >> m >> k;
- for(int i = 1; i <= k; i++) {
- int x, y; cin >> x >> y;
- banned[x][y] = true;
- }
- auto node = [&](int i, int j) -> int {
- return (i - 1) * m + j;
- };
- auto inside = [&](int i, int j) -> bool {
- return (i > 0 && j > 0 && i <= n && j <= m && !banned[i][j]);
- };
- Dinitz G = Dinitz(n * m + 5, 0, n * m + 1);
- for(int i = 1; i <= n; i++) {
- for(int j = 1; j <= m; j++) {
- if(banned[i][j]) continue;
- if(node(i, j) & 1) G.addEdge(0, node(i, j), 1);
- else G.addEdge(node(i, j), n * m + 1, 1);
- }
- }
- TWOSAT S = TWOSAT(n * m);
- for(int i = 1; i <= n; i++) {
- for(int j = 1; j <= m; j++) {
- if(!(node(i, j) & 1) || banned[i][j]) continue;
- for(int r = 0; r < 8; r++) {
- int x = i + dx[r], y = j + dy[r];
- if(!inside(x, y)) continue;
- G.addEdge(node(i, j), node(x, y), 1);
- S.addEdge(node(i, j), node(x, y));
- }
- }
- }
- int flow = G.Flow();
- vector<pii> mf = G.getEdge();
- int numNodes = n * m;
- for(int i = 0; i < mf.size(); i++) {
- int u = mf[i].fi, v = mf[i].se;
- ok[u] = ok[v] = true;
- S.addEdge(u + numNodes, v + numNodes);
- }
- for(int i = 1; i <= n * m; i++) {
- if(!ok[i]) S.addEdge(i + numNodes, i + numNodes);
- }
- vector<int> notChosen = S.do2SAT();
- for(int i = 0; i < notChosen.size(); i++) {
- int id = notChosen[i];
- int u = (id - 1) / m + 1, v = (id - 1) % m + 1;
- banned[u][v] = true;
- }
- vector<pii> ans;
- for(int i = 1; i <= n; i++) {
- for(int j = 1; j <= m; j++) {
- if(!banned[i][j]) ans.pb(make_pair(i, j));
- }
- }
- cout << ans.size() << '\n';
- for(int i = 0; i < ans.size(); i++) {
- cout << ans[i].fi << " " << ans[i].se << '\n';
- }
- }
- int main()
- {
- ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
- #ifndef ONLINE_JUDGE
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #else
- //online
- #endif
- int tc = 1, ddd = 0;
- // cin >> tc;
- while(tc--) {
- //ddd++;
- //cout << "Case #" << ddd << ": ";
- solve();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement