zoukankan      html  css  js  c++  java
  • HIT 2715 Matrix3

    HIT_2715

        这个题目和HIT_2543比较像,每个点有两种性质,走第一次的时候会花费w,后面再走花费就会变为0。于是不妨将一个点拆成两个点,并连两条边,一条为容量为1花费为w的边,另一条为容量为INF花费为0的边。再将其余的边连好之后做最大费用最大流即可,由于题目限制行走过程中不会出现环,所以就不必担心有正圈了。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXN 50
    #define MAXD 5010
    #define MAXM 35010
    #define INF 0x3f3f3f3f
    #define NINF 0xc3c3c3c3
    int N, K, h[MAXN][MAXN], first[MAXD], e, next[MAXM], u[MAXM], v[MAXM], flow[MAXM], cost[MAXM];
    int S, T, q[MAXD], dis[MAXD], pre[MAXD], inq[MAXD];
    const int Q = 2500;
    int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
    void add(int x, int y, int f, int c)
    {
        u[e] = x, v[e] = y, flow[e] = f, cost[e] = c;
        next[e] = first[x], first[x] = e ++;    
    }
    void init()
    {
        int i, j, k, ni, nj, x, y, nx, w;
        scanf("%d%d", &N, &K);
        S = 0, T = N * N * 2 + 1;
        memset(first, -1, sizeof(first[0]) * (T + 1)), e = 0;
        for(i = 1; i <= N; i ++)
            for(j = 1; j <= N; j ++)
            {
                x = (i - 1) * N + j, y = N * N + x;
                scanf("%d", &w);
                add(x, y, 1, w), add(y, x, 0, -w), add(x, y, INF, 0), add(y, x, 0, 0);
            }
        for(i = 1; i <= N; i ++) for(j = 1; j <= N; j ++) scanf("%d", &h[i][j]);
        for(i = 1; i <= N; i ++)
            for(j = 1; j <= N; j ++)
            {
                x = (i - 1) * N + j, y = N * N + x;
                add(S, x, INF, 0), add(x, S, 0, 0);
                if(i == 1 || i == N || j == 1 || j == N)
                    add(y, T, INF, 0), add(T, y, 0, 0);
                for(k = 0; k < 4; k ++)
                {
                    ni = i + dx[k], nj = j + dy[k];
                    if(ni >= 1 && ni <= N && nj >= 1 && nj <= N && h[ni][nj] < h[i][j])
                    {
                        nx = (ni - 1) * N + nj;
                        add(y, nx, INF, 0), add(nx, y, 0, 0);    
                    }    
                }
            }
    }
    int bfs()
    {
        int i, x, front, rear;
        front = rear = 0;
        memset(dis, 0xc3, sizeof(dis[0]) * (T + 1));
        dis[S] = 0, pre[S] = -1, q[rear ++] = S;
        memset(inq, 0, sizeof(inq[0]) * (T + 1));
        while(front != rear)
        {
            x = q[front ++], inq[x] = 0;
            front > Q ? front = 0 : 0;
            for(i = first[x]; i != -1; i = next[i])
                if(flow[i] && dis[x] + cost[i] > dis[v[i]])
                {
                    dis[v[i]] = dis[x] + cost[i], pre[v[i]] = i;
                    if(!inq[v[i]])
                    {
                        q[rear ++] = v[i], inq[v[i]] = 1;
                        rear > Q ? rear = 0 : 0;    
                    }
                }
        }
        return dis[T] != NINF;
    }
    void solve()
    {
        int i, j, c = 0, a, cnt = 0;
        while((++ cnt) <= K && bfs())
        {
            for(i = pre[T], a = INF; i != -1; i = pre[u[i]])
                a = std::min(a, flow[i]);
            if(a > 1)
                break;
            for(i = pre[T]; i != -1; i = pre[u[i]])
                flow[i] -= a, flow[i ^ 1] += a;
            c += dis[T];
        }
        printf("%d\n", c);
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            init();
            solve();
        }
        return 0;    
    }
  • 相关阅读:
    mycat分表扩展之全局序列(数据库方式)
    mycat分表扩展之按日期(天)分片
    mycat分表扩展之范围约定
    mycat分表扩展之分片枚举
    jdk导入证书链步骤说明
    oracle md5加密函数
    oracle常用(11g)
    oracle 11g 常规sql
    oracle归档日志
    oracle定时任务
  • 原文地址:https://www.cnblogs.com/staginner/p/2640017.html
Copyright © 2011-2022 走看看