Skip to content

Commit 75034ad

Browse files
committed
P10940
1 parent 5384ec0 commit 75034ad

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

code/luogu/P10940.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#include <iostream>
2+
#include <iterator>
3+
#include <queue>
4+
#include <unordered_set>
5+
#include <vector>
6+
7+
template <typename T>
8+
struct Flow {
9+
int n;
10+
struct Edge {
11+
int to;
12+
T cap;
13+
Edge(int to, T cap) : to(to), cap(cap) {}
14+
};
15+
std::vector<Edge> edge;
16+
std::vector<std::vector<int>> adj;
17+
std::vector<int> cur, dep;
18+
explicit Flow(int n) : n(n), adj(n) {}
19+
bool bfs(int s, int t) {
20+
dep.assign(n, -1);
21+
std::queue<int> q;
22+
dep[s] = 0;
23+
q.push(s);
24+
while (!q.empty()) {
25+
int node = q.front();
26+
q.pop();
27+
for (int i : adj[node]) {
28+
int to = edge[i].to;
29+
T c = edge[i].cap;
30+
if (c > 0 && dep[to] == -1) {
31+
dep[to] = dep[node] + 1;
32+
if (to == t) return true;
33+
q.push(to);
34+
}
35+
}
36+
}
37+
return false;
38+
}
39+
T dfs(int node, int t, T flow) {
40+
if (node == t || flow == 0) return flow;
41+
T f, res = 0;
42+
for (int &i = cur[node]; i < int(adj[node].size()); ++i) {
43+
int j = adj[node][i], to = edge[j].to;
44+
T c = edge[j].cap;
45+
if (dep[to] == dep[node] + 1 &&
46+
(f = dfs(to, t, std::min(flow, c)))) {
47+
res += f, flow -= f;
48+
edge[j].cap -= f, edge[j ^ 1].cap += f;
49+
}
50+
if (flow == 0) break;
51+
}
52+
if (!res) dep[node] = -1;
53+
return res;
54+
}
55+
int add_edge(int u, int v, T c) {
56+
int j = edge.size();
57+
adj[u].push_back(edge.size());
58+
edge.emplace_back(v, c);
59+
adj[v].push_back(edge.size());
60+
edge.emplace_back(u, 0);
61+
return j;
62+
}
63+
T operator()(int s, int t, const T INF = 1e9) {
64+
T ans = 0;
65+
while (bfs(s, t)) cur.assign(n, 0), ans += dfs(s, t, INF);
66+
return ans;
67+
}
68+
};
69+
70+
struct SCC {
71+
int n;
72+
std::vector<std::vector<int>> adj;
73+
std::vector<int> stk;
74+
std::vector<int> dfn, low, bel;
75+
int cur, cnt;
76+
void dfs(int x) {
77+
dfn[x] = low[x] = cur++;
78+
stk.push_back(x);
79+
for (int to : adj[x]) {
80+
if (dfn[to] == -1) {
81+
dfs(to);
82+
low[x] = std::min(low[x], low[to]);
83+
} else if (bel[to] == -1) {
84+
low[x] = std::min(low[x], dfn[to]);
85+
}
86+
}
87+
if (dfn[x] == low[x]) {
88+
int y;
89+
do {
90+
y = stk.back();
91+
bel[y] = cnt;
92+
stk.pop_back();
93+
} while (y != x);
94+
++cnt;
95+
}
96+
}
97+
98+
public:
99+
explicit SCC(int n)
100+
: n(n), adj(n), dfn(n, -1), low(n), bel(n, -1), cur(0), cnt(0) {}
101+
102+
void add_edge(int u, int v) { adj[u].push_back(v); }
103+
std::vector<int> operator()() {
104+
for (int i = 0; i < n; i++)
105+
if (dfn[i] == -1) dfs(i);
106+
return bel;
107+
}
108+
};
109+
110+
void solve() {
111+
int n, m, t;
112+
std::cin >> n >> m >> t;
113+
114+
std::vector<std::pair<int, int>> edge_list(t);
115+
for (auto &[u, v] : edge_list) {
116+
std::cin >> u >> v;
117+
--u, --v;
118+
}
119+
120+
auto f = Flow<int>(n + m + 2);
121+
for (const auto [u, v] : edge_list) {
122+
f.add_edge(u, n + v, 1);
123+
}
124+
for (int i = 0; i < n; ++i) f.add_edge(n + m, i, 1);
125+
for (int i = 0; i < m; ++i) f.add_edge(n + i, n + m + 1, 1);
126+
f(n + m, n + m + 1);
127+
128+
auto b = SCC(f.n);
129+
std::unordered_set<int> matching;
130+
for (int u = 0; u < f.n; ++u) {
131+
for (int id : f.adj[u]) {
132+
auto [v, cap] = f.edge[id];
133+
if (cap) {
134+
// std::cout << u << ' ' << v << '\n';
135+
b.add_edge(u, v);
136+
}
137+
if (u < n && v < n + m && !cap) {
138+
matching.insert(u * m + v - n);
139+
}
140+
}
141+
}
142+
auto bel = b();
143+
144+
std::vector<int> ans;
145+
for (int i = 0; i < t; ++i) {
146+
auto [u, v] = edge_list[i];
147+
if (bel[u] != bel[n + v] && !matching.contains(u * m + v)) {
148+
ans.push_back(i + 1);
149+
}
150+
}
151+
152+
std::cout << ans.size() << '\n';
153+
std::copy(ans.begin(), ans.end(),
154+
std::ostream_iterator<int>(std::cout, " "));
155+
std::cout << '\n';
156+
}
157+
158+
int main() {
159+
std::ios::sync_with_stdio(false);
160+
std::cin.tie(nullptr);
161+
162+
solve();
163+
}

0 commit comments

Comments
 (0)