Cod sursa(job #829714)

Utilizator vendettaSalajan Razvan vendetta Data 5 decembrie 2012 19:15:50
Problema Matrice 2 Scor 55
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.12 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];
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[3][301];

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[linie][j];
            //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, int y){

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

}

void fa_graf(){

    for(int i=1; i<=n; ++i){
        for(int j=1; j<=n; ++j){
            for(int k=0; k<4; ++k){
                int new_i = i + dx[k];
                int new_j = j + dy[k];
                if (check(new_i, new_j) ){
                    int x = 0; int y = 0;
                    transforma( i, j, new_i, new_j, x, y );
                    v[++cnt] = make_pair( make_pair(x, y), min(a[i][j], a[new_i][new_j]) );
                }
            }
        }
    }

}

bool cmp( pair< pair<int,int>, int> a, pair< pair<int,int>, int > b){

    return (a.second > b.second);

}

int afla(int x){

    int cpy = x;
    for(; t[x] != 0; x=t[x]);
    while(cpy != x){
        int unde = t[cpy];
        t[cpy] = x;
        cpy = unde;
    }
    return x;

}

void uneste(int x, int y){

    t[x] = y;

}

void fa_apm(){

    //fac apm de cost maxim
    sort(v+1, v+cnt+1, cmp);

    for(int i=1; i<=cnt; ++i){
        int x = v[i].first.first;
        int y = v[i].first.second;
        int c = v[i].second;
        int radx = afla(x); int rady = afla(y);
        if (radx == rady) continue;// sunt in aceeasi componenta
        uneste(radx, rady);
        //cout << x << " " << y << " " << c << "\n";
        gf[x].push_back( make_pair(y, c) );
        gf[y].push_back( make_pair(x, c) );
    }

}


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;

}