Cod sursa(job #830017)

Utilizator vendettaSalajan Razvan vendetta Data 6 decembrie 2012 10:38:38
Problema Matrice 2 Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.76 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

ifstream f("matrice2.in");
ofstream g("matrice2.out");

#define nmax (301*301)
#define ll long long
#define Ceva 17
#define inf (1<<29)

const int dx[] = {0, -1, 0, 1};
const int dy[] = {-1, 0, 1, 0};

const int h = 200;

int n, m, t[nmax],nivel[nmax], d[nmax];
bool viz[nmax];
int rezMin[Ceva][nmax], cine[Ceva][nmax];
int t2[nmax];
vector< pair<int,int> > gf[nmax];
int cnt;
//pair< pair<int,int>, int> v[nmax*2];
int a[nmax];
 set< pair<int,int> > S;
void citeste(){

    f >> n >> m;
    int k = 0;
    for(int i=1; i<=n; ++i){
        int linie = 0;
        if (i & 1) linie = 1;
        for(int j=1; j<=n; ++j){
            ++k;
            //f >> a[i][j];
            f >> a[k];
            //fac muchiile
            //if (k - n > 0) v[++cnt] = make_pair( make_pair(k, k-n), min(a[linie][j], a[1-linie][j]) );
            //if (j - 1 > 0) v[++cnt] = make_pair( make_pair(k, k-1), min(a[linie][j], a[linie][j-1]) );
        }
    }

}


void transforma(int x1, int y1, int x2, int y2, int &i, int &j){

    i = (n * x1) - (n - y1);
    j = (n * x2) - (n - y2);

}

inline bool check(int x){

    if (x > 0 && x <= n*n) return 1;
    return 0;

}



void fa_apm(){

    //fac apm de cost maxim
    int N = n*n;
    for(int i=2; i<nmax; ++i) d[i] = inf;
    S.insert( make_pair(0, 1) );

    const int dnod[] = {-1, -n, n, 1};

    for(; S.size(); ){
        set<pair<int,int> > ::iterator it;
        it = S.end();
        --it;

        int nod = (*it).second;
        S.erase(it);
        if (viz[nod] == 1) continue;
        viz[nod] = 1;
        for(int k=0; k<4; ++k){
            int new_nod = k + dnod[k];
            if (check(nod) && d[new_nod] > min(a[nod], a[new_nod]) && viz[new_nod] == 0){
                d[new_nod] = min(a[nod], a[new_nod]);
                t[new_nod] = nod;
                S.insert( make_pair( d[new_nod], new_nod));
            }
        }
    }

    for(int i=2; i<=n*n; ++i){
        gf[i].push_back( make_pair(t[i], d[i]));
        gf[ t[i] ].push_back( make_pair(i, d[i]));
    }

}


void init(int tata, int nod, int cost){

    rezMin[0][nod] = cost;
    cine[0][nod] = tata;// cien ii al 2 ^ 0 tata pt nod

}

void dfs(int nod, int n2, int niv){

    viz[nod] = 1;
    t2[nod] = n2;
    if (niv % h == 0) n2 = nod;
    nivel[nod] = niv;

    for(int i=0; i<gf[nod].size(); ++i){
        int vc = gf[nod][i].first;
        if (viz[vc] == 0){
            init(nod, vc, gf[nod][i].second);//initializez rmq-ul pt muchia minima
            t[vc] = nod;
            dfs(vc, n2, niv+1);
        }
    }

}

void fa_muchie(){

    //acum aflu muchia minima
    for(int i=1; i<17; ++i){
        int put = (1<<i);
        for(int j=1; j<=n*n; ++j){
            int new_x = cine[i-1][j];
            cine[i][j] = cine[i-1][new_x];
            rezMin[i][j] = min(rezMin[i-1][j], rezMin[i-1][new_x]);
        }
    }

}


void afla_lca(int &Lca, int x, int y){

    while(t2[x] != t2[y]){
        if (nivel[x] > nivel[y]){
            x = t2[x];
        }else y = t2[y];
    }

    while(x != y){
        if (nivel[x]>nivel[y]){
            x = t[x];
        }else y = t[y];
    }

    Lca = x;

}

void afla_cost(int nod, int lca, int &cost){

    int k = nivel[nod] - nivel[lca];// al cate-lea tata e lca
    //cout << " K: " << k << " " << nod << " " << lca << "\n";
    for(int i=17; i>=0; --i){
        if ( ( k & (1<<i) ) != 0 ){
            cost = min(cost, rezMin[i][nod]);
            nod = cine[i][nod];
        }
    }

}
void rezolva(){

    //fa_graf();

    fa_apm();

    for(int i=0; i<nmax; ++i) t[i] = 0;//numai am nevoie de ei; o sa am nevoie la muchia minima

    //initializez pt muchia minima
    for(int i=0; i<17; ++i){
        for(int j=0; j<nmax; ++j) rezMin[i][j] = inf;
    }
    dfs(1,0,1);

    //acum aflu muchia minima de pe drumul  x-lca, y-lca
    fa_muchie();

    //acum raspund la query-uri

    for(int i=1; i<=m; ++i){
        int x1, y1, x2, y2;
        f >> x1 >> y1 >> x2 >> y2;
        int X = 0; int Y = 0;
        transforma(x1, y1, x2, y2, X, Y);
        //aflu lca-ul dintre X si Y;
        int Lca = 0;
        afla_lca(Lca, X, Y);
        int cost_min = inf;
        afla_cost(X, Lca, cost_min);
        afla_cost(Y, Lca, cost_min);
        //cout << X << " " << Y << " " << Lca << " " << nivel[X] << " " << nivel[Lca] << " " << nivel[Y]<< "\n";
        cout << cost_min << "\n";
        g << cost_min << "\n";
    }

}

int main(){

    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;

}