QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#676762#9424. Stop the Castle 2ucup-team5367#WA 0ms3636kbC++236.4kb2024-10-26 00:18:432024-10-26 00:18:44

Judging History

This is the latest submission verdict.

  • [2024-10-26 00:18:44]
  • Judged
  • Verdict: WA
  • Time: 0ms
  • Memory: 3636kb
  • [2024-10-26 00:18:43]
  • Submitted

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)