2018-german-collegiate-programming-contest-gcpc-18-en-Problem M: Mountaineers

  The Chilean Andes have become increasingly popular as a destination for backpacking and hiking. Many parts of the Andes are quite remote and thus dangerous. Because of this, the Ministry of Tourism wants to help travelers plan their trips. In particular, the travelers need to know how high they will have to climb during their journey, as this information will help them decide which equipment they need to bring. The Ministry has tasked you to provide the aspiring mountaineers with this data.
 You are given a topographic map of a part of the Andes, represented as a two-dimensional grid of height values, as well as the list of origins and destinations. Mountaineers can move from each grid cell to any of the four adjacent cells. For each mountaineer find the minimal height that they must be able to reach in order to complete their journey.
Input
The input consists of:

  • one line with three integers m, n and q (1 ≤ m, n ≤ 500, 1 ≤ q ≤ 10510^{5}), where m is thenumber of rows, n is the number of columns, and q is the number of mountaineers;
  • one line with three integers m, n and q (1 ≤ m, n ≤ 500, 1 ≤ q ≤ 10510^{5}), where m is the number of rows, n is the number of columns, and q is the number of mountaineers;
  • m lines, each with n integers h1, . . . , hn (1 ≤ hi ≤ 106), the height values in the map;
  • q lines, each with four integers x1, y1, x2, y2 (1 ≤ x1, x2 ≤ m, 1 ≤ y1, y2 ≤ n), describing a mountaineer who wants to trek from (x1, y1) to (x2, y2).

The top left cell of the grid has coordinates (1, 1) and the bottom right cell has coordinates(m, n).

Output
Output q integers, the minimal height for each mountaineer, in the same order as in the input.

Sample Input 1           Sample Output 1

3 5 3                 2
1 3 2 1 3                4
2 4 5 4 4                2
2 1 3 2 2
1 1 3 2
2 4 2 2
1 4 3 4

題意:
給你一個鄰接矩陣,每個數值代表的是這個位置的高度,然後問你兩個位置之間的路徑的最大值的最小化是多少
題解
先把高度按從小到大排,然後依次遍歷,遍歷的過程判斷該位置的四周有沒有已經被遍歷的,如果有就需要連一條本身到該位置的邊(因爲之後遍歷的肯定是高度更高的,所以連邊,代表高度高的是父親),然後要做個並查集,把已經連過的都並在一起,所以連的其實是目前遍歷的點和之前遍歷的點的並查集,因爲之前的所有點都是小於目前點的高度,所以之前的所有點要到當前點最大高度最小化就是目前遍歷點的高度。看代碼就知道了,很容易理解的

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int>P;

int a[509][509];

P h[250009];
bool vis[250009];
int nx[]={0,1,0,-1};
int ny[]={1,0,-1,0};
int bin[250009],head[250009],dep[250009];
int f[250009][21];
int val[250009];

int find(int x){
    return bin[x]=bin[x]==x?x:find(bin[x]);
}
int cnt=0;
struct rt{
    int v,next;
}edge[250009];
void add(int u,int v){
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

void bfs(int s)
{
    queue<int>Q;
    Q.push(s);
//    f[s][0]=s;
    dep[s] = 1;
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            dep[v]=dep[u]+1;
            f[v][0] = u;
            for(int j = 1; j <= 20; j++) f[v][j] = f[f[v][j-1]][j-1];
            Q.push(v);
        }
    }
}

int lca(int x, int y)
{
    if(dep[x] > dep[y]) swap(x, y);
    for(int i = 20; i >= 0; i--)
        if(dep[f[y][i]] >= dep[x]) y = f[y][i];
    if(x == y) return x;

    for(int i = 20; i >= 0; i--)
        if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    return f[x][0];
}

int main(){
    int n,m,q;
    while(~scanf("%d%d%d",&n,&m,&q)){
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n*m;i++)bin[i]=i;
        int tot=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                h[tot].first = a[i][j];
                h[tot].second = (i-1)*m+j;
                val[(i-1)*m+j]=a[i][j];
                tot++;
            }
        }
        sort(h,h+tot);
        for(int i=0;i<tot;i++){
            int u=h[i].second;
            int x=(u-1)/m+1,y=u-(x-1)*m;
            vis[u]=1;
            for(int j=0;j<4;j++){
                int sx=x+nx[j],sy=y+ny[j];
                int v = (sx-1)*m+sy;
                if(sx>=1&&sx<=n&&sy>=1&&sy<=m&&vis[v]){
                    int fx=find(v);
                    if(fx==u)continue;
                    bin[fx]=u;
                    add(u,fx);
                }
            }
        }
        bfs(h[tot-1].second);
        int x1,y1,x2,y2;
        for(int i=1;i<=q;i++){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            int p=lca((x1-1)*m+y1,(x2-1)*m+y2);
            printf("%d\n",val[p]);
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章