[USACO13FEB]Tractor【二分 + BFS】

Pro

Luogu3073

Sol

好水的一道题啊……直接二分答案就可以过,不需要并查集的,二分加广搜,时间复杂度是O(n^2 logM),能过的。

读完题,我们很容易的就能知道,答案满足单调性,也就是说,如果mid能够到达一半以上,那么>mid的所有的数都可以达到一半以上,于是就会有一个临界值是达到和达不到之间的,这个值就是我们最终的答案。经分析得,本题满足二分条件,可以二分。二分出来,我们正着做广搜,搜索的路上就能求出最大的联通块,如果最大的联通块比一半要多,右端点移动,反之左端点移动。

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;

void read(int &x)
{
    char c = getchar(); x = 0;
    while(c < '0' || c > '9') c = getchar();
    while(c <= '9' && c >= '0') x = x*10+c-48, c = getchar();
}

void put(int x)  
{  
    int num = 0; char c[15];
    while(x) c[++num] = (x%10)+48, x /= 10;
    while(num) putchar(c[num--]);
    putchar('\n'); 
}

struct Node {
    int x , y;
    Node(){}
    Node (int xx , int yy) {
        x = xx , y = yy;
    }
};
int n , map[505][505] , minn = 1e8 , maxx = -1 , vis[505][505] , K;

inline int mymax(int a , int b) { return a>b?a:b; }
inline int mymin(int a , int b) { return a<b?a:b; }
inline int myabs(int a) { return a>0?a:(-a); }
inline int mypow(int a , int b) { if(b == 1) return a; int t = mypow(a , b/2); if(b % 2 == 0) return t*t; return t*t*a; }

int bfs(int x , int y , int k) {
    int res = 1;
    vis[x][y] = 1;
    queue<Node>q; 
    q.push(Node(x , y));
    while(!q.empty()) {
        Node u = q.front();
        q.pop();
        if(u.x-1>=1 && !vis[u.x-1][u.y] && myabs(map[u.x-1][u.y]-map[u.x][u.y])<=k) {
            vis[u.x-1][u.y] = 1;
            res++;
            q.push(Node(u.x-1,u.y));
        }
        if(u.x+1<=n && !vis[u.x+1][u.y] && myabs(map[u.x+1][u.y]-map[u.x][u.y])<=k) {
            vis[u.x+1][u.y] = 1;
            res++;
            q.push(Node(u.x+1,u.y));
        }
        if(u.y-1>=1 && !vis[u.x][u.y-1] && myabs(map[u.x][u.y-1]-map[u.x][u.y])<=k) {
            vis[u.x][u.y-1] = 1;
            res++;
            q.push(Node(u.x,u.y-1));
        }
        if(u.y+1<=n && !vis[u.x][u.y+1] && myabs(map[u.x][u.y+1]-map[u.x][u.y])<=k) {
            vis[u.x][u.y+1] = 1;
            res++;
            q.push(Node(u.x,u.y+1));
        }
    }
    return res;
}

int jud(int x) {
    int ans = 0;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            if(!vis[i][j])
                ans = mymax(ans , bfs(i,j,x));
    if(ans >= K)
        return 1;
    return 0;
} 

int main() {
    read(n);
    K = mypow(n , 2) / 2;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++) {
            read(map[i][j]);
            minn = mymin(minn , map[i][j]);
            maxx = mymax(maxx , map[i][j]);     
        }
    int l = 0 , r = maxx - minn; 
    while(l <= r) {
        memset(vis , 0 , sizeof(vis)); 
        int mid = (l+r)>>1;
        if(jud(mid))
            r = mid - 1;
        else
            l = mid + 1;
    } 
    put(l);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43061009/article/details/82108235
今日推荐