QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#676762 | #9424. Stop the Castle 2 | ucup-team5367# | WA | 0ms | 3636kb | C++23 | 6.4kb | 2024-10-26 00:18:43 | 2024-10-26 00:18:44 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int,int>;
template<typename T>
using bstring = basic_string<T>;
const ll INFL = 1e18;
#define all(x) x.begin(), x.end()
/*
from https://github.com/defnotmee/definitely-not-a-lib
Uses Dinic's algorithm to calculate the maximum flow between
s and t in a graph.
O(V^2E) in general, O(Esqrt(V)) on unit networks (edges that are
not connected to s or t have unit capacity, like in matching).
Usage: Declare FlowGraph(n,s,t) and add edges to it. When done, call
max_flow(). It returns the maximum flow between s and t. By default,
s = 0 and t = n-1.
After calling max_flow, the edges with EVEN indices on FlowGraph::edges
will have the "flow" variable corresponding to the ammount of flow passing
through them in the answer dinic provides.
*/
// #ifndef O_O
// #include"../utility/template.cpp"
// #endif
struct FlowEdge {
ll u, v, cap, flow = 0;
ll to(ll id){
return id == u ? v : u;
}
};
struct FlowGraph{
int n;
int s, t;
vector<FlowEdge> edges;
vector<bstring<int>> g;
FlowGraph(int n = 0, int _s = 0, int _t = -1) : n(n), s(_s), t(_t), g(n){
if(t == -1)
t = n-1;
}
void add_edge(ll u, ll v, ll cap){
g[u].push_back(edges.size());
edges.push_back({u,v,cap});
g[v].push_back(edges.size());
edges.push_back({v,u,0});
}
ll max_flow(){
ll ret = 0;
while(true){
ll cur = block_flow();
if(!cur)
break;
ret+=cur;
}
return ret;
}
private:
vector<int> ptr, dist;
ll block_flow(){
ll ret = 0;
dist = bfs();
ptr = vector<int>(n);
return dfs(s,INFL); // INFL needs to be >= than the max flow of the graph
}
vector<int> bfs(){
vector<int> dist(n,n);
queue<int> q;
dist[s] = 0;
q.push(s);
while(!q.empty()){
int cur = q.front();
q.pop();
for(int eid : g[cur]){
FlowEdge cedge = edges[eid];
int to = cedge.to(cur);
if(cedge.cap == cedge.flow)
continue;
if(dist[to] > dist[cur]+1){
dist[to] = dist[cur]+1;
q.push(to);
}
}
}
return dist;
}
ll dfs(int id, ll pushed){
if(pushed == 0)
return 0;
if(id == t)
return pushed;
ll rem = pushed;
while(rem && ptr[id] < g[id].size()){
int eid = g[id][ptr[id]];
int to = edges[eid].to(id);
ptr[id]++;
if(dist[id] >= dist[to])
continue;
ll usable = min(rem, edges[eid].cap-edges[eid].flow);
ll used = dfs(to,usable);
edges[eid].flow+=used;
edges[eid^1].flow-=used;
rem-=used;
}
return pushed-rem;
}
};
int main(){
cin.tie(0)->sync_with_stdio(0);
int n, m, k;
cin >> n >> m >> k;
set<int> vals;
map<int,int> tr;
vector<pii> torre(n), block(m);
for(auto& [a,b] : torre){
cin >> a >> b;
vals.insert(a);
vals.insert(b);
}
for(auto& [a,b] : block){
cin >> a >> b;
vals.insert(a);
vals.insert(b);
}
for(auto i : vals){
tr[i] = tr.size();
}
for(auto& [a,b] : torre){
a = tr[a];
b = tr[b];
}
for(auto& [a,b] : block){
a = tr[a];
b = tr[b];
}
int l = vals.size();
struct item {
int x;
int id;
bool operator<(item b) const {
return x < b.x;
}
};
vector<bstring<item>> torrex(l);
vector<bstring<item>> torrey(l);
for(int i = 0; i < n; i++){
torrex[torre[i].first].push_back({torre[i].second, i});
torrey[torre[i].second].push_back({torre[i].first, i});
}
int tot = 0;
for(auto & i : torrex)
sort(i.begin(),i.end()), tot+=max(0, int(i.size())-1);
for(auto & i : torrey)
sort(i.begin(),i.end()), tot+=max(0, int(i.size())-1);
FlowGraph dinic(2*n+2);
for(int i = 0; i < n; i++)
dinic.add_edge(0,i+1,1), dinic.add_edge(i+n+1,2*n+1,1);
auto add_bip =[&](int a, int b){
dinic.add_edge(a+1,b+n+1,1);
};
map<pii, int> id_from_edge;
auto get_edge =[&] (int id)-> pii {
auto [x,y] = block[id];
int idx = lower_bound(all(torrex[x]), item{y,0})-torrex[x].begin();
int rx;
if(idx == torrex[x].size() || !idx)
rx = -1;
else rx = torrex[x][idx].id;
int idy = lower_bound(all(torrey[y]), item{x,0})-torrey[y].begin();
int ry;
if(idy == torrey[y].size() || !idy)
ry = -1;
else ry = torrey[y][idy].id;
return {rx, ry};
};
vector<pii> c_block(m);
for(int i = 0; i < m; i++){
c_block[i] = get_edge(i);
if(c_block[i].first != -1 && c_block[i].second != -1)
add_bip(c_block[i].first,c_block[i].second), id_from_edge[c_block[i]] = i;
}
dinic.max_flow();
vector<int> safea(n), safeb(n);
set<int> resp;
for(int i = 0; i < m; i++)
resp.insert(i);
for(auto [a,b,cap,flow] : dinic.edges){
if(resp.size() > k && flow == 1 && 1 <= a && a <= n && n+1 <= b && b <= 2*n ){
a--, b -= n+1;
safea[a]=1;
safeb[b]=1;
tot-=2;
resp.erase(id_from_edge[{a,b}]);
}
}
for(int i = 0; i < m; i++){
auto [a,b] = c_block[i];
if(a != -1 && !safea[a] && resp.size() > k){
safea[a] = 1;
tot--;
resp.erase(id_from_edge[{a,b}]);
}
if(b != -1 && !safeb[b] && resp.size() > k){
safeb[b] = 1;
tot--;
resp.erase(id_from_edge[{a,b}]);
}
}
cout << tot << '\n';
while(resp.size() > k)
resp.erase(resp.begin());
for(int i : resp)
cout << i+1 << ' ';
cout << '\n';
}
详细
Test #1:
score: 0
Wrong Answer
time: 0ms
memory: 3636kb
input:
3 8 6 4 1 3 2 1 2 6 4 1 4 7 6 1 6 3 6 6 2 3 3 1 4 3 4 6 5 2 6 4 3 2 1 10 12 10 10 10 11 1 4 1 5 1 3 2 1 1 2 1 2 2 2 3
output:
1 3 4 5 6 7 8
result:
wrong answer Participant states the answer to be 1 but is actually 5 (test case 1)