Game HDU - 3657(最小割)

Game

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1563    Accepted Submission(s): 664


php

Problem Description
onmylove has invented a game on n × m grids. There is one positive integer on each grid. Now you can take the numbers from the grids to make your final score as high as possible. The way to get score is like
the following:
● At the beginning, the score is 0;
● If you take a number which equals to x, the score increase x;
● If there appears two neighboring empty grids after you taken the number, then the score should be decreased by 2(x&y). Here x and y are the values used to existed on these two grids. Please pay attention that "neighboring grids" means there exits and only exits one common border between these two grids.

Since onmylove thinks this problem is too easy, he adds one more rule:
● Before you start the game, you are given some positions and the numbers on these positions must be taken away.
Can you help onmylove to calculate: what's the highest score onmylove can get in the game?
 

 

Input
Multiple input cases. For each case, there are three integers n, m, k in a line.
n and m describing the size of the grids is n ×m. k means there are k positions of which you must take their numbers. Then following n lines, each contains m numbers, representing the numbers on the n×m grids.Then k lines follow. Each line contains two integers, representing the row and column of one position
and you must take the number on this position. Also, the rows and columns are counted start from 1.
Limits: 1 ≤ n, m ≤ 50, 0 ≤ k ≤ n × m, the integer in every gird is not more than 1000.
 

 

Output
For each test case, output the highest score on one line.
 

 

Sample Input
2 2 1 2 2 2 2 1 1 2 2 1 2 7 4 1 1 1
 

 

Sample Output
4 9
Hint
As to the second case in Sample Input, onmylove gan get the highest score when calulating like this: 2 + 7 + 4 - 2 × (2&4) - 2 × (2&7) = 13 - 2 × 0 - 2 × 2 = 9.
 

 

Author
onmylove
 

 

Source
 
 
解析:
  棋盘问题的变形 多了点限制
  遇到这种问题就向最小割去想    最小割就是求最小价值损失
  对于预先选定的点 x   若是是白点 则 s 向 x 连一条INF的边  若是是黑点 则 x 向 t 连一条INF的边  由于权值为INF  因此不管怎样 这条边都不会成为割边 因此就能表明这条边已经被选择
  其它的就和棋盘问题同样  只不过相邻的点的边权   加了限制以后 把这条边的权值 由棋盘问题的INF 改成 2 * (w1 & w2)便可
跑一遍Dinic    而后sum - Dinic
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <cctype>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <bitset>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define rb(a) scanf("%lf", &a)
#define rf(a) scanf("%f", &a)
#define pd(a) printf("%d\n", a)
#define plld(a) printf("%lld\n", a)
#define pc(a) printf("%c\n", a)
#define ps(a) printf("%s\n", a)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 1e5 + 10, INF = 0x7fffffff;
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int n, m, k, s, t;
int way[55][55], vv[2550][2550];
int head[maxn], cur[maxn], vis[maxn], d[maxn], cnt, nex[maxn << 1];

struct node
{
    int u, v, c;
}Node[maxn << 1];

void add_(int u, int v, int c)
{
    Node[cnt].u = u;
    Node[cnt].v = v;
    Node[cnt].c = c;
    nex[cnt] = head[u];
    head[u] = cnt++;
}

void add(int u, int v, int c)
{
    add_(u, v, c);
    add_(v, u, 0);
}

bool bfs()
{
    queue<int> Q;
    mem(d, 0);
    Q.push(s);
    d[s] = 1;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        for(int i = head[u]; i != -1; i = nex[i])
        {
            int v = Node[i].v;
            if(!d[v] && Node[i].c > 0)
            {
                d[v] = d[u] + 1;
                Q.push(v);
                if(v == t) return 1;
            }
        }
    }
    return d[t] != 0;
}

int dfs(int u, int cap)
{
    int ret = 0;
    if(u == t || cap == 0)
        return cap;
    for(int &i = cur[u]; i != -1; i = nex[i])
    {
        int v = Node[i].v;
        if(d[v] == d[u] + 1 && Node[i].c > 0)
        {
            int V = dfs(v, min(cap, Node[i].c));
            Node[i].c -= V;
            Node[i ^ 1].c += V;
            ret += V;
            cap -= V;
            if(cap == 0) break;
        }
    }
    if(cap > 0) d[u] = -1;
    return ret;
}

int Dinic()
{
    int ans = 0;
    while(bfs())
    {
        memcpy(cur, head, sizeof head);
        ans += dfs(s, INF);
    }
    return ans;
}

int main()
{
    while(scanf("%d%d%d", &n, &m, &k) != EOF)
    {
        int sum = 0;
        s = 0, t = n * m + 1;
        mem(head, -1), cnt = 0, mem(vv, 0);
        int w, x, y;
        rap(i, 1, n)
            rap(j, 1, m)
                rd(way[i][j]), sum += way[i][j];
        rap(i, 1, k)
        {
            rd(x), rd(y);
            if((x + y) & 1)
                add(s, (x - 1) * m + y, INF);
            else add((x - 1) * m + y, t, INF);
            vv[x][y] = 1;
        }
        rap(i, 1, n)
            rap(j, 1, m)
            {
                rep(k, 0, 4)
                {
                    int nx = i + dir[k][0];
                    int ny = j + dir[k][1];
                    if(nx < 1 || ny < 1 || nx > n || ny > m) continue;
                    if((i + j) & 1)
                        add((i - 1) * m + j, (nx - 1) * m + ny, 2 * (way[i][j] & way[nx][ny]));
                }
                if(vv[i][j]) continue;
                if((i + j) & 1) add(s, (i - 1) * m + j, way[i][j]);
                else add((i - 1) * m + j, t, way[i][j]);
            }
        cout << sum - Dinic() << endl;

    }



    return 0;
}

 

  
 
Game

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1563    Accepted Submission(s): 664


node

Problem Description
onmylove has invented a game on n × m grids. There is one positive integer on each grid. Now you can take the numbers from the grids to make your final score as high as possible. The way to get score is like
the following:
● At the beginning, the score is 0;
● If you take a number which equals to x, the score increase x;
● If there appears two neighboring empty grids after you taken the number, then the score should be decreased by 2(x&y). Here x and y are the values used to existed on these two grids. Please pay attention that "neighboring grids" means there exits and only exits one common border between these two grids.

Since onmylove thinks this problem is too easy, he adds one more rule:
● Before you start the game, you are given some positions and the numbers on these positions must be taken away.
Can you help onmylove to calculate: what's the highest score onmylove can get in the game?
 

 

Input
Multiple input cases. For each case, there are three integers n, m, k in a line.
n and m describing the size of the grids is n ×m. k means there are k positions of which you must take their numbers. Then following n lines, each contains m numbers, representing the numbers on the n×m grids.Then k lines follow. Each line contains two integers, representing the row and column of one position
and you must take the number on this position. Also, the rows and columns are counted start from 1.
Limits: 1 ≤ n, m ≤ 50, 0 ≤ k ≤ n × m, the integer in every gird is not more than 1000.
 

 

Output
For each test case, output the highest score on one line.
 

 

Sample Input
2 2 1 2 2 2 2 1 1 2 2 1 2 7 4 1 1 1
 

 

Sample Output
4 9
Hint
As to the second case in Sample Input, onmylove gan get the highest score when calulating like this: 2 + 7 + 4 - 2 × (2&4) - 2 × (2&7) = 13 - 2 × 0 - 2 × 2 = 9.
 

 

Author
onmylove
 

 

Source
 
本身选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要可以为了当时纯粹的梦想和感动坚持努力下去,无论其它人怎么样,咱们也可以保持本身的本色走下去。