Submission #1227775

#TimeUsernameProblemLanguageResultExecution timeMemory
1227775spetrParking (CEOI22_parking)C++20
28 / 100
138 ms40808 KiB
#include <bits/stdc++.h>
using namespace std;

#define fi first
#define se second
#define all(v) (v).begin(), (v).end()
#define pb push_back
#define REP(i,n) for(int i=0,_n=(n); i<_n; ++i)
#define FORE(i,a,b) for(int i=(a),_b=(b); i<=_b; ++i)

typedef pair<int,int> pii;

void process(){
    int N,M;
    cin>>N>>M;
    vector<int> bot(M), top(M);
    vector<vector<int>> pos(N, vector<int>(2,-1));
    vector<vector<int>> adj(2*M);
    vector<int> sz(M,0), emp;
    emp.reserve(M);

    // 1) Načíst bot/top, nastavit sz[i] a vyplnit emp
    REP(i,M){
        cin>>bot[i]>>top[i];
        if(bot[i]>0)  sz[i]++;
        if(top[i]>0) sz[i]++;
    }
    REP(i,M){
        if(sz[i]==0) emp.pb(i);
    }
    // 2) Naplnit pos[] a vnitro-hrany full spotů
    REP(i,M){
        if(bot[i]>0){
            int c=bot[i]-1;
            pos[c][ pos[c][0]!=-1 ] = i<<1;
        }
        if(top[i]>0){
            int c=top[i]-1;
            pos[c][ pos[c][0]!=-1 ] = i<<1|1;
            if(bot[i]>0 && bot[i]!=top[i]){
                adj[i<<1].pb(i<<1|1);
                adj[i<<1|1].pb(i<<1);
            }
        }
    }
    // 3) Pomocná lambda pro prázdný spot
    auto get_empty=[&](){
        while(!emp.empty() && sz[emp.back()]>0) emp.pop_back();
        if(emp.empty()){ cout<<-1<<"\n"; exit(0); }
        return emp.back();
    };
    // 4) Napojit dvojice stejných barev
    REP(c,N){
        int u=pos[c][0], v=pos[c][1];
        if(u>=0 && v>=0 && u!=(v^1)){
            adj[u].pb(v);
            adj[v].pb(u);
        }
    }
    // 5) Přesuny
    vector<pii> res;
    auto mv=[&](int x,int y){
        int sx=x>>1, sy=y>>1;
        res.emplace_back(sx,sy);
        // odebírám z x
        sz[sx]--;
        if(sz[sx]==0) emp.pb(sx);
        // přidávám do y
        if(sz[sy]==0){
            // pokud tam bylo nula, spot už v emp, ale dle definice
            // necháváme, get_empty se postará
        }
        sz[sy]++;
    };
    // 6) Rozplétání cest (kóduju přímo inline stejnou logiku)
    vector<bool> used(2*M,false);
    vector<vector<int>> paths, cycles;
    // 6a) extract chains
    REP(i,2*M){
        if(!used[i] && adj[i].size()==1){
            vector<int> path;
            int u=i, p=-1;
            while(true){
                used[u]=true; path.pb(u);
                int nxt=-1;
                for(int v:adj[u]) if(v!=p){ nxt=v; break; }
                if(nxt==-1) break;
                p=u; u=nxt;
            }
            paths.pb(path);
        }
    }
    // 6b) solve each chain
    for(auto &path: paths){
        int n = path.size();
        for(int i=0;i+1<n;i+=2){
            if(path[i+1]&1){
                mv(path[i+1], path[i]);
            } else {
                // najdu nejdřív top-pár
                int p=i;
                for(;p+1<n;p+=2){
                    if((path[p]&1) && (path[p+1]&1)) break;
                }
                if(p+1<n){
                    int e = get_empty()<<1;
                    mv(path[p],e);
                    mv(path[p+1],e);
                }
                for(int j=p-2;j>=i;j-=2){
                    mv(path[j], path[j+1]);
                }
                i=p;
            }
        }
    }
    // 7) extract cycles
    auto del_edge=[&](int x,int y){
        auto it=find(all(adj[x]),y);
        if(it!=adj[x].end()) adj[x].erase(it);
        it=find(all(adj[y]),x);
        if(it!=adj[y].end()) adj[y].erase(it);
    };
    REP(i,2*M){
        if(!used[i] && adj[i].size()==2){
            vector<int> cyc;
            int u=i, p=-1;
            while(!used[u]){
                used[u]=true;
                cyc.pb(u);
                int nxt = (adj[u][0]==p?adj[u][1]:adj[u][0]);
                p=u; u=nxt;
            }
            cyc.pb(cyc[0]);
            // solve one cycle inline
            int m=cyc.size(), ps=-1;
            for(int j=0;j+1<m;j++){
                if((cyc[j]&1)&&(cyc[j+1]&1)){ ps=j; break; }
            }
            if(ps>=0){
                int e = get_empty()<<1;
                mv(cyc[ps],e); mv(cyc[ps+1], e);
                int prv = (ps?cyc[ps-1]:cyc[m-2]);
                int nxt = (ps+2<m?cyc[ps+2]:cyc[1]);
                del_edge(prv, cyc[ps]);
                del_edge(cyc[ps], cyc[ps+1]);
                del_edge(cyc[ps+1], nxt);
                cyc.erase(cyc.begin()+ps, cyc.begin()+ps+2);
                rotate(cyc.begin(), cyc.begin()+ps, cyc.end());
                // zacyklení do cesty
                int nn=cyc.size();
                for(int j=0;j+1<nn;j+=2){
                    if(cyc[j+1]&1) mv(cyc[j+1],cyc[j]);
                    else{
                        int pe=j;
                        for(;pe+1<nn;pe+=2){
                            if((cyc[pe]&1)&&(cyc[pe+1]&1)) break;
                        }
                        if(pe+1<nn){
                            int ee = get_empty()<<1;
                            mv(cyc[pe],ee); mv(cyc[pe+1],ee);
                        }
                        for(int k=pe-2;k>=j;k-=2)
                            mv(cyc[k],cyc[k+1]);
                        j=pe;
                    }
                }
            } else {
                cyc.pop_back();
                if(cyc[0]&1){
                    rotate(cyc.begin(),cyc.begin()+1,cyc.end());
                }
                if(cyc[0]==(cyc[1]^1)){
                    rotate(cyc.begin(),cyc.begin()+1,cyc.end());
                    reverse(all(cyc));
                }
                int e = get_empty()<<1;
                mv(cyc.back(), e);
                int szc=cyc.size();
                for(int j=1;j+2<szc;j+=2) mv(cyc[j],cyc[j-1]);
                mv(cyc[szc-2], e);
            }
        }
    }

    cout<<res.size()<<"\n";
    for(auto &p:res) cout<<p.fi+1<<" "<<p.se+1<<"\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    process();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...