zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer (最大生成树+LCA求节点距离)

    ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer

    J. Maze Designer

    After the long vacation, the maze designer master has to do his job. A tour company gives him a map which is a rectangle. The map consists of N imes MN×M little squares. That is to say, the height of the rectangle is NN and the width of the rectangle is MM. The master knows exactly how the maze is going to use. The tour company will put a couple in two different squares in the maze and make them seek each other. Of course,the master will not make them find each other easily. The only thing the master does is building some wall between some little squares. He knows in that way, wherever the couple is put, there is only one path between them. It is not a difficult thing for him, but he is a considerate man. He also knows that the cost of building every wall between two adjacent squares is different(Nobody knows the reason). As a result, he designs the maze to make the tour company spend the least money to build it.

    Now, here's your part. The tour company knows you're the apprentice of the master, so they give you a task. you're given QQ qustions which contain the information of where the couple will be put. You need to figure out the length of the shortest path between them.

    However,the master doesn't tell you how he designs the maze, but he believes that you, the best student of himself, know the way. So he goes on vacation again.

    Input

    The first line of the input contains two integers NN and MM (1 le N,M le 5001≤N,M≤500), giving the number of rows and columns of the maze.

    The next N imes MN×M lines of the input give the information of every little square in the maze, and their coordinates are in order of (1,1)(1,1) , (1,2)(1,2) cdots⋯ (1,M)(1,M) , (2,1)(2,1) , (2,2)(2,2) , cdots⋯ , (2,M)(2,M) , cdots⋯ ,(N,M)(N,M).

    Each line contains two characters DD and RR and two integers aa , bb (0 le a,b le 20000000000≤a,b≤2000000000 ), aa is the cost of building the wall between it and its lower adjacent square, and bb is the cost of building the wall between it and its right adjacent square. If the side is boundary, the lacking path will be replaced with X 00.

    The next line contains an integer QQ (1 le Q le 1000001≤Q≤100000 ), which represents the number of questions.

    The next QQ lines gives four integers, x_1x1, y_1y1, x_2x2, y_2y2 ( 1 le x_11≤x1 , x_2 le Nx2≤N , 1 le y_11≤y1 , y_2 le My2≤M ), which represent two squares and their coordinate are (x_1x1 , y_1y1) and (x_2x2 , y_2y2).

    (xx,yy) means row xx and column yy.

    It is guaranteed that there is only one kind of maze.

    Output

    For each question, output one line with one integer which represents the length of the shortest path between two given squares.

    样例输入复制

    3 3
    D 1 R 9
    D 7 R 8
    D 4 X 0
    D 2 R 6
    D 12 R 5
    D 3 X 0
    X 0 R 10
    X 0 R 11
    X 0 X 0
    3
    1 1 3 3
    1 2 3 2
    2 2 3 1
    

    样例输出复制

    4
    2
    2
    

    题目来源

    [ACM-ICPC 2018 徐州赛区网络预赛](https://nanti.jisuanke.com/acm?kw=ACM-ICPC 2018 徐州赛区网络预赛)

    题面:

    有一个n*m的空地,可以在每个空地之间建墙,多个询问,问从某一点到另外一点的有且只有一条路并且建墙的总代价最小时的路径长度

    思路:

    假设开始所有的墙都已经建好了,现在开始拆墙,保证拆的墙一定是最大的,然后算两点之间的距离

    解法:拆墙就是找最大生成树,算两点之间的距离用个LCA, 因为有多组询问

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define du2(a,b) scanf("%d %d",&(a),&(b))
    #define du1(a) scanf("%d",&(a));
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
    void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    
    inline void getInt(int* p);
    const int maxn = 300010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int n, m;
    #define  N maxn
    int getid(int x, int y)
    {
        return m * (x - 1) + y;
    }
    struct NODE
    {
        int next;
        int dis;
        NODE() {
    
        }
        NODE(int nn, int dd)
        {
            next = nn;
            dis = dd;
        }
    };
    std::vector<NODE> son[N];
    int depth[N], fa[N][21], in[N], a, b;
    ll dist[N];
    // depth[i] -> i 节点的深度
    // fa[i][j] -> i 节点向上移动2^j个节点后的祖先
    // fa[i][0] -> i 向上移动1个节点后的祖先,即父节点
    // in[i] i节点的入度,用来找树根用的。
    // a b 为读边用的。
    void addegde(int a, int b, ll dis)
    {
        cout << a << " " << b << " " << dis << endl;
        son[a].push_back(NODE(b, dis));
        son[b].push_back(NODE(a, dis));
    }
    void dfs(int rt, int prev, int dis)
    {
        depth[rt] = depth[prev] + 1;
        dist[rt] = dist[prev] + 1ll;
        fa[rt][0] = prev;
        for (int i = 1; i < 20; i++)
        {
            fa[rt][i] = fa[fa[rt][i - 1]][i - 1];
        }
        for (int i = 0; i < son[rt].size(); i++)
        {
            if (son[rt][i].next == prev)
                continue;
            dfs(son[rt][i].next, rt, son[rt][i].dis);
        }
    }
    int LCA(int x, int y)
    {
        if (depth[x] < depth[y])
            swap(x, y);
        for (int i = 19; i >= 0; i--)
        {
            if (depth[x] - (1 << i) >= depth[y])
            {
                x = fa[x][i];
            }
        }
        if (x == y)
        {
            return x;
        }
        for (int i = 19; i >= 0; i--)
        {
            if (fa[x][i] != fa[y][i])
            {
                x = fa[x][i];
                y = fa[y][i];
            }
        }
        return fa[x][0];
    }
    ll finddist(int a, int b)
    {
        ll u = LCA(a, b);
        ll L = dist[a] + dist[b] - 2 * dist[u];
        return L;
    }
    struct node
    {
        int f, t;
        ll w;
        node() {}
        node(int ff, int tt, ll ww)
        {
            f = ff;
            t = tt;
            w = ww;
        }
        bool operator < (const node& b) const
        {
            return w > b.w;
        }
    };
    std::vector<node> v;
    int far[maxn];
    void init(int N)
    {
        repd(i, 1, N)
        {
            far[i] = i;
        }
        depth[0] = -1;
    }
    int findpar(int x)
    {
        return far[x] == x ? x : far[x] = findpar(far[x]);
    }
    void mg(int a, int b, ll w)
    {
        int aa = a;
        int bb = b;
        a = findpar(a);
        b = findpar(b);
        if (a != b)
        {
            far[a] = b;
            addegde(aa, bb, w);
        }
    }
    void K()
    {
        init(n * m);
        sort(ALL(v));
        for (int i = 0; i < sz(v); ++i)
        {
            mg(v[i].f, v[i].t, v[i].w);
        }
    }
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        gbtb;
        cin >> n >> m;
        char op;
        ll w;
        repd(i, 1, n)
        {
            repd(j, 1, m)
            {
                cin >> op >> w;
                if (op == 'D')
                {
                    v.push_back(node(getid(i, j), getid(i + 1, j), w));
                }
                cin >> op >> w;
                if (op == 'R')
                {
                    v.push_back(node(getid(i, j), getid(i , j + 1), w));
                }
            }
        }
        K();
        dfs(1, 0, 0ll);
        int q;
        cin >> q;
        int x1, yy1, x2, y2;
        while (q--)
        {
            cin >> x1 >> yy1 >> x2 >> y2;
            cout << finddist(getid(x1, yy1), getid(x2, y2)) << endl;
        }
    
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    自动化测试项目实战训练【广州8月】
    RFT基础使用手册
    TestComplete自动化测试实战训练【6月11、12号】
    Jubula Eclipse开源功能测试工具
    网络管理自动化测试应用
    IBM RFT自动化测试实战课程
    GUI自动化测试原理剖析—JAVA测试篇
    简易自动化测试设计之(一) 基于RFT的自动化测试层次
    录制,到底给我们带来了什么?
    IBM Rational Functional Tester(RFT) 自动化测试框架ITCL
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11778396.html
Copyright © 2011-2022 走看看