Skip to content

Commit 37bf6f1

Browse files
committed
QOJ: Stop the Castle 2
1 parent 9802ccf commit 37bf6f1

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

QOJ/9424.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#include <bits/stdc++.h>
2+
using namespace std;
3+
4+
#define endl '\n'
5+
6+
#define maxn 200005
7+
8+
typedef pair<int, int> pii;
9+
10+
class Dinic {
11+
private:
12+
struct Edge {
13+
int to, cap, rev, id;
14+
};
15+
16+
vector<vector<Edge>> graph;
17+
vector<vector<Edge>::iterator> cur;
18+
vector<int> dist;
19+
queue<int> que;
20+
int n, S, T;
21+
22+
bool bfs(void) {
23+
for (int i = 1; i <= n; i++) dist[i] = INT_MAX, cur[i] = graph[i].begin();
24+
que.push(S), dist[S] = 0;
25+
while (!que.empty()) {
26+
int p = que.front();
27+
que.pop();
28+
for (auto i : graph[p])
29+
if (dist[i.to] > dist[p] + 1 && i.cap) dist[i.to] = dist[p] + 1, que.push(i.to);
30+
}
31+
return dist[T] != INT_MAX;
32+
}
33+
int dfs(int p, int rest) {
34+
if (p == T) return rest;
35+
int used = 0, c;
36+
for (auto i = cur[p]; i != graph[p].end() && rest; i++) {
37+
cur[p] = i;
38+
if (!i->cap || dist[i->to] != dist[p] + 1) continue;
39+
if (!(c = dfs(i->to, min(rest, i->cap)))) dist[i->to] = -1;
40+
used += c, rest -= c, i->cap -= c, graph[i->to][i->rev].cap += c;
41+
}
42+
return used;
43+
}
44+
45+
public:
46+
vector<bool> avai;
47+
set<int> edges[2];
48+
49+
void resize(int _n) { return n = _n, graph.resize(n + 1), cur.resize(n + 1), dist.resize(n + 1), avai.resize(n + 1); }
50+
void addEdge(int from, int to, int cap, int id) {
51+
return graph[from].push_back(Edge{to, cap, (int)graph[to].size(), id}),
52+
graph[to].push_back(Edge{from, 0, (int)graph[from].size() - 1, 0});
53+
}
54+
int solve(int _S, int _T) {
55+
S = _S, T = _T;
56+
int flow = 0;
57+
while (bfs()) flow += dfs(S, INT_MAX);
58+
for (int i = 1; i <= n; i++)
59+
for (auto j : graph[i])
60+
if (j.id) edges[!j.cap].insert(j.id);
61+
return flow;
62+
}
63+
};
64+
65+
map<int, set<pii>> R, C;
66+
int nx[maxn], ny[maxn];
67+
bool vis[maxn];
68+
vector<int> rec[maxn];
69+
70+
void solve(void) {
71+
R.clear(), C.clear();
72+
73+
int n, m, k;
74+
cin >> n >> m >> k;
75+
76+
Dinic dnc;
77+
int S = 2 * n + 1, T = S + 1;
78+
dnc.resize(T);
79+
80+
for (int i = 1, x, y; i <= n; i++)
81+
cin >> x >> y, R[x].emplace(y, i), C[y].emplace(x, i), dnc.addEdge(S, i, 1, 0), dnc.addEdge(n + i, T, 1, 0);
82+
for (int i = 1; i <= 2 * n; i++) rec[i].clear(), vis[i] = false;
83+
int ans = 0;
84+
for (auto &i : R) ans += (int)i.second.size() - 1;
85+
for (auto &i : C) ans += (int)i.second.size() - 1;
86+
for (int i = 1, x, y; i <= m; i++) {
87+
cin >> x >> y, nx[i] = -1, ny[i] = -1;
88+
if (R.count(x)) {
89+
auto p = R[x].lower_bound({y, 0});
90+
if (p != R[x].begin() && p != R[x].end()) dnc.avai[nx[i] = p->second] = true;
91+
}
92+
if (C.count(y)) {
93+
auto p = C[y].lower_bound({x, 0});
94+
if (p != C[y].begin() && p != C[y].end()) dnc.avai[ny[i] = n + p->second] = true;
95+
}
96+
if (nx[i] != -1 && ny[i] != -1) dnc.addEdge(nx[i], ny[i], 1, i);
97+
}
98+
// cerr << "! " << ans << endl;
99+
int cnt = m - k, flow = dnc.solve(S, T);
100+
if (flow >= cnt) {
101+
cout << ans - cnt * 2 << endl;
102+
for (int i = 1; i <= m; i++)
103+
if (!dnc.edges[1].count(i) || !cnt)
104+
cout << i << ' ';
105+
else
106+
cnt--;
107+
cout << endl;
108+
return;
109+
}
110+
cnt -= flow, ans -= flow * 2;
111+
for (int i = 1; i <= m; i++)
112+
if (!dnc.edges[1].count(i)) {
113+
if (nx[i] != -1) rec[nx[i]].push_back(i);
114+
if (ny[i] != -1) rec[ny[i]].push_back(i);
115+
} else
116+
vis[nx[i]] = vis[ny[i]] = true;
117+
// cerr << "# " << cnt << endl;
118+
for (int i = 1; i <= m; i++) {
119+
if (dnc.edges[1].count(i)) continue;
120+
if (nx[i] != -1 && !vis[nx[i]] && cnt) vis[nx[i]] = true, dnc.edges[1].insert(i), ans--, cnt--;
121+
if (ny[i] != -1 && !vis[ny[i]] && cnt) vis[ny[i]] = true, dnc.edges[1].insert(i), ans--, cnt--;
122+
}
123+
// cerr << "# " << cnt << endl;
124+
for (int i = 1; i <= m; i++)
125+
if (!dnc.edges[1].count(i) && cnt) dnc.edges[1].insert(i), cnt--;
126+
127+
// cerr << "###" << endl;
128+
cout << ans << endl;
129+
for (int i = 1; i <= m; i++)
130+
if (!dnc.edges[1].count(i)) cout << i << ' ';
131+
cout << endl;
132+
133+
return;
134+
}
135+
136+
int main() {
137+
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
138+
139+
int _ = 1;
140+
cin >> _;
141+
while (_--) solve();
142+
143+
return 0;
144+
}

0 commit comments

Comments
 (0)