結果
| 問題 |
No.1744 Selfish Spies 1 (à la Princess' Perfectionism)
|
| コンテスト | |
| ユーザー |
shobonvip
|
| 提出日時 | 2025-11-17 14:51:50 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 92 ms / 5,000 ms |
| コード長 | 8,882 bytes |
| コンパイル時間 | 2,876 ms |
| コンパイル使用メモリ | 233,796 KB |
| 実行使用メモリ | 11,412 KB |
| 最終ジャッジ日時 | 2025-11-17 14:51:55 |
| 合計ジャッジ時間 | 5,711 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 39 |
ソースコード
/**
author: shobonvip
created: 2025.11.17 14:16:14
**/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()
template <typename T> bool chmin(T &a, const T &b) {
if (a <= b) return false;
a = b;
return true;
}
template <typename T> bool chmax(T &a, const T &b) {
if (a >= b) return false;
a = b;
return true;
}
template <typename T> T max(vector<T> &a){
assert(!a.empty());
T ret = a[0];
for (int i=0; i<(int)a.size(); i++) chmax(ret, a[i]);
return ret;
}
template <typename T> T min(vector<T> &a){
assert(!a.empty());
T ret = a[0];
for (int i=0; i<(int)a.size(); i++) chmin(ret, a[i]);
return ret;
}
template <typename T> T sum(vector<T> &a){
T ret = 0;
for (int i=0; i<(int)a.size(); i++) ret += a[i];
return ret;
}
struct scc_graph {
int n, k;
vector<vector<int>> g, rg;
vector<int> vs, cmp, seen;
void dfs(int v) {
seen[v] = 1;
for(int u : g[v]) {
if(seen[u] < 0) dfs(u);
}
vs.emplace_back(v);
}
void rdfs(int v) {
cmp[v] = k;
for(int u : rg[v]) {
if(cmp[u] < 0) rdfs(u);
}
}
scc_graph(int _n) : n(_n), g(_n), rg(_n) {}
void add_edge(int f, int t) {
g[f].emplace_back(t);
rg[t].emplace_back(f);
}
vector<vector<int>> scc() {
seen.assign(n, -1);
rep(i, 0, n) {
if(seen[i] < 0) dfs(i);
}
reverse(all(vs));
cmp.assign(n, -1);
k = 0;
for(int v : vs) {
if(cmp[v] < 0) {
rdfs(v);
k++;
}
}
vector<vector<int>> ret(k);
rep(i, 0, n) { ret[cmp[i]].emplace_back(i); }
return ret;
}
};
// all hash: cb5cee
template<class Cap> struct mf_graph {
struct nedge {
int to, rev;
Cap cap;
};
int nn;
vector<pair<int, int>> pos;
vector<vector<nedge>> g;
mf_graph() : nn(0) {}
explicit mf_graph(int n) : nn(n), g(n) {}
int add_edge(int from, int to, Cap cap) {
int m = pos.size();
pos.push_back({from, int(g[from].size())});
int frid = int(g[from].size());
int toid = int(g[to].size());
if(from == to) toid++;
g[from].push_back(nedge{to, toid, cap});
g[to].push_back(nedge{from, frid, 0});
return m;
}
Cap flow(int s, int t) { return flow(s, t, numeric_limits<Cap>::max()); }
Cap flow(int s, int t, Cap flow_limit) {
vector<int> lv(nn), iter(nn);
queue<int> q;
auto bfs = [&]() {
fill(all(lv), -1);
lv[s] = 0;
queue<int>().swap(q);
q.push(s);
while(!q.empty()) {
int v = q.front();
q.pop();
for(auto e : g[v]) {
if(e.cap == 0 || lv[e.to] >= 0) continue;
lv[e.to] = lv[v] + 1;
if(e.to == t) return;
q.push(e.to);
}
}
};
auto dfs = [&](auto self, int v, Cap up) {
if(v == s) return up;
Cap res = 0;
int lvvv = lv[v];
for(int& i = iter[v]; i < int(g[v].size()); i++) {
nedge& e = g[v][i];
if(lvvv <= lv[e.to] || g[e.to][e.rev].cap == 0) continue;
Cap d = self(self, e.to, min(up - res, g[e.to][e.rev].cap));
if(d <= 0) continue;
g[v][i].cap += d;
g[e.to][e.rev].cap -= d;
res += d;
if(res == up) return res;
}
lv[v] = nn;
return res;
};
Cap flow = 0;
while(flow < flow_limit) {
bfs();
if(lv[t] == -1) break;
fill(all(iter), 0);
Cap f = dfs(dfs, t, flow_limit - flow);
if(!f) break;
flow += f;
}
return flow;
}
/*
struct edge {
int from, to;
Cap cap, flow;
};
edge get_edge(int i) {
int m = int(pos.size());
auto _e = g[pos[i].first][pos[i].second];
auto _re = g[_e.to][_e.rev];
return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap};
}
vector<bool> min_cut(int s) {
vector<bool> visited(nn);
queue<int> q;
q.push(s);
while(!q.empty()) {
int p = q.front();
q.pop();
visited[p] = true;
for(auto e : g[p]) {
if(e.cap && !visited[e.to]) {
visited[e.to] = true;
q.push(e.to);
}
}
}
return visited;
}
vector<edge> edges() {
int m = int(pos.size());
vector<edge> result;
for(int i = 0; i < m; i++) { result.push_back(get_edge(i)); }
return result;
}
*/
};
vector<pair<vector<int>,vector<int>>>
dm_decomposition(int L, int R, vector<pair<int,int>> edges) {
for (auto [x, y]: edges) {
assert(0 <= x && x < L);
assert(0 <= y && y < R);
}
mf_graph<int> mf(L+R+2);
for (auto [x, y]: edges) {
mf.add_edge(x, y+L, 1);
}
rep(i,0,L) mf.add_edge(L+R, i, 1);
rep(i,0,R) mf.add_edge(i+L, L+R+1, 1);
mf.flow(L+R, L+R+1);
vector<int> match(L+R, -1);
rep(x,0,L) {
for (auto &e: mf.g[x]) {
if (L <= e.to && e.to < L+R && e.cap == 0) {
match[x] = e.to;
match[e.to] = x;
}
}
}
scc_graph scc(L+R);
for (auto [x,y]: edges) {
scc.add_edge(x, y+L);
}
rep(i,0,L) {
if (match[i] >= L) scc.add_edge(match[i], i);
}
auto ns = scc.scc();
vector<int> cmp_map(ns.size(), -2);
vector<int> vis(L+R);
vector<int> st;
rep(c,0,2) {
vector<vector<int>> to(L+R);
auto color = [&L](int x) {
return x >= L;
};
for (auto [u, v]: edges) {
v += L;
if (color(u) != c) swap(u, v);
to[u].push_back(v);
if(match[u] == v) to[v].push_back(u);
}
rep(i,0,L+R) {
if (match[i]>=0 || color(i) != c || vis[i]) continue;
vis[i] = 1; st = {i};
while(!st.empty()) {
int now = st.back();
cmp_map[scc.cmp[now]] = c-1;
st.pop_back();
for (int nxt: to[now]) {
if (!vis[nxt]) {
vis[nxt] = 1;
st.push_back(nxt);
}
}
}
}
}
int nset = 1;
rep(n,0,(int)ns.size()) {
if (cmp_map[n] == -2) cmp_map[n] = nset++;
}
for (auto &x: cmp_map) {
if (x==-1) x = nset;
}
nset++;
vector<pair<vector<int>,vector<int>>> groups(nset);
rep(i,0,L){
if (match[i]<0) continue;
int c = cmp_map[scc.cmp[i]];
groups[c].first.push_back(i);
groups[c].second.push_back(match[i]-L);
}
rep(i,0,L) {
if (match[i]>=0) continue;
int c = cmp_map[scc.cmp[i]];
groups[c].first.push_back(i);
}
rep(i,0,R) {
if (match[L+i]>=0) continue;
int c = cmp_map[scc.cmp[L+i]];
groups[c].second.push_back(i);
}
return groups;
}
// https://hitonanode.github.io/cplib-cpp/graph/test/dulmage_mendelsohn.yuki1615.test.cpp
std::vector<std::pair<std::vector<int>, std::vector<int>>>
verify_dulmage_mendelsohn(int L, int R, const std::vector<std::pair<int, int>> &edges) {
auto ret = dm_decomposition(L, R, edges);
assert(ret.size() >= 2);
vector<int> lord(L, -1), rord(R, -1);
set<pair<int, int>> edges_set(edges.begin(), edges.end());
for (int igrp = 0; igrp < int(ret.size()); ++igrp) {
for (int vl : ret[igrp].first) {
assert(lord[vl] < 0);
lord[vl] = igrp;
}
for (int vr : ret[igrp].second) {
assert(rord[vr] < 0);
rord[vr] = igrp;
}
if (igrp == 0) {
assert(ret[igrp].first.size() < ret[igrp].second.size() or ret[igrp].first.empty());
} else if (igrp + 1 == int(ret.size())) {
assert(ret[igrp].first.size() > ret[igrp].second.size() or ret[igrp].second.empty());
} else {
assert(ret[igrp].first.size() == ret[igrp].second.size());
assert(ret[igrp].first.size());
}
for (int j = 0; j < min<int>(ret[igrp].first.size(), ret[igrp].second.size()); ++j) {
auto u = ret[igrp].first[j], v = ret[igrp].second[j];
assert(edges_set.count(make_pair(u, v)));
}
}
assert(count(lord.begin(), lord.end(), -1) == 0);
assert(count(rord.begin(), rord.end(), -1) == 0);
for (auto e : edges) {
assert(0 <= e.first and e.first < L);
assert(0 <= e.second and e.second < R);
assert(lord.at(e.first) <= rord.at(e.second)); // Check topological order
}
return ret;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N, M, L;
cin >> N >> M >> L;
vector<pair<int, int>> edges(L);
for (auto &[s, t] : edges) {
cin >> s >> t;
--s, --t;
}
auto dm = verify_dulmage_mendelsohn(N, M, edges);
set<pair<int, int>> fixed;
for (auto [us, vs] : dm) {
if (us.size() == 1 and vs.size() == 1) fixed.emplace(us[0], vs[0]);
}
for (auto [s, t] : edges) cout << (fixed.count(make_pair(s, t)) ? "No" : "Yes") << '\n';
}
shobonvip