QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#676764#9424. Stop the Castle 2ucup-team5367#WA 124ms11316kbC++236.8kb2024-10-26 00:19:522024-10-26 00:19:52

Judging History

This is the latest submission verdict.

  • [2024-10-26 00:19:52]
  • Judged
  • Verdict: WA
  • Time: 124ms
  • Memory: 11316kb
  • [2024-10-26 00:19:52]
  • 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 t;
    cin >> t;

    while(t--){
        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: 100
Accepted
time: 0ms
memory: 3640kb

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:

4
2 3 5 6 
2
2 
0
2 3 

result:

ok ok 3 cases (3 test cases)

Test #2:

score: -100
Wrong Answer
time: 124ms
memory: 11316kb

input:

1224
11 17 14
7 3
4 2
8 13
3 15
3 4
5 11
10 2
3 3
8 6
7 11
2 3
10 4
1 3
12 1
2 5
11 9
11 6
11 10
8 15
1 5
9 14
4 11
1 6
10 7
7 6
11 4
8 4
1 11
18 3 2
14 8
2 14
13 13
9 12
14 12
5 6
8 1
10 5
8 6
8 9
6 6
7 5
12 11
6 11
13 5
1 10
7 6
14 5
6 15
2 4
11 1
1 6 4
14 14
13 9
9 3
10 12
7 5
8 13
9 14
1 9 8
4 9...

output:

7
4 5 6 7 8 9 10 11 12 13 14 15 16 17 
15
2 3 
0
3 4 5 6 
0
2 3 4 5 6 7 8 9 
11
2 3 
8
1 2 3 
0
1 2 3 4 5 6 7 8 9 10 11 12 
1
6 7 8 9 10 11 12 
8
17 18 19 
1
1 2 3 4 5 6 7 8 
7
7 8 
10
13 14 15 
1
10 11 12 13 14 15 16 17 18 19 20 
0
1 
1
2 3 
0
5 6 7 
7
11 12 13 14 15 
2
10 11 12 13 14 
4
3 4 5 6 7 ...

result:

wrong answer Participant states the answer to be 7 but is actually 8 (test case 1)