BZOJ 1976 BeiJing2010組隊 能量魔方 Cube 最小割

來源:互聯網
上載者:User

標籤:bzoj   最小割   最大流   網路流   

題目大意

給出一個N×N×N的矩陣,矩陣上的每一個方塊可以塗上兩種顏色,相鄰的兩個方塊如果塗上了不同的顏色,就會產生一點能量。現在已知了一些方塊的顏色,問最多可以產生多少點能量。

思路

假設所有相鄰的方塊之間全部都產生能量,且不考慮已經上好色的方塊,之後減去不合法的就行了。
一般來說這種相鄰的方塊之間會產生一些什麼的一般都是把所有點染色,一種顏色的與S相連,另一種與T相連。這道題中,左側的點若是最終屬於S集,代表這個點上了P色,否則上了N色;右側的點若是最終屬於T集,代表這個點上了P色,否則上了N色。在最後的答案中,我們只記錄P色周圍有多少N色,而不討論N色周圍有多少P色。
因為現在我們假設的是所有的塊之間都產生能量,所以先從S到所有左側的點連上流量為這個點周圍相鄰的點的個數,右側的點同理。如果一個點並不是P色,那麼它就要失去所有的能量(因為只記錄P色產生的能量)。
如果左邊的點和右邊的點不在同一個集合的話(也就是它們之間的邊被割開了),那麼他們最後的顏色就是相同的,因此不會產生能量,左側和右側各減1,所以這個邊的流量就是2。
之後跑個Dinic就行了。。。

CODE
#define _CRT_SECURE_NO_WARNINGS#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 50#define MAXP (MAX * MAX * MAX)#define MAXE 1000010#define INF 0x3f3f3f3f#define S 0#define T (MAXP - 1)using namespace std;#define INRANGE(x, y, z) (x * y * z && x <= m && y <= m && z <= m)const int dx[] = {0, 1, -1, 0, 0, 0, 0};const int dy[] = {0, 0, 0, 1, -1, 0, 0};const int dz[] = {0, 0, 0, 0, 0, 1, -1};struct MaxFlow{    int head[MAXP], total;    int next[MAXE], aim[MAXE], flow[MAXE];    int deep[MAXP];    MaxFlow():total(1) {}    void Add(int x, int y, int f) {        next[++total] = head[x];        aim[total] = y;        flow[total] = f;        head[x] = total;    }    void Insert(int x, int y, int f) {        Add(x, y, f);        Add(y, x, 0);    }    bool BFS() {        static queue<int> q;        while(!q.empty())   q.pop();        memset(deep, 0, sizeof(deep));        deep[S] = 1;        q.push(S);        while(!q.empty()) {            int x = q.front(); q.pop();            for(int i = head[x]; i; i = next[i])                if(flow[i] && !deep[aim[i]]) {                    deep[aim[i]] = deep[x] + 1;                    q.push(aim[i]);                    if(aim[i] == T) return true;                }        }        return false;    }    int Dinic(int x, int f) {        if(x == T)  return f;        int temp = f;        for(int i = head[x]; i; i = next[i])            if(flow[i] && deep[aim[i]] == deep[x] + 1 && temp) {                int away = Dinic(aim[i], min(flow[i], temp));                if(!away)   deep[aim[i]] = 0;                flow[i] -= away;                flow[i^1] += away;                temp -= away;            }        return f - temp;    }}solver;int m;char src[MAX][MAX][MAX];int num[MAX][MAX][MAX], cnt;int ans;int main(){    cin >> m;    for(int i = 1; i <= m; ++i)        for(int j = 1; j <= m; ++j)            scanf("%s", src[i][j] + 1);    for(int i = 1; i <= m; ++i)        for(int j = 1; j <= m; ++j)            for(int k = 1; k <= m; ++k)                num[i][j][k] = ++cnt;    for(int i = 1; i <= m; ++i)        for(int j = 1; j <= m; ++j)            for(int k = 1; k <= m; ++k) {                int near = 0;                for(int d = 1; d <= 6; ++d) {                    int fx = i + dx[d];                    int fy = j + dy[d];                    int fz = k + dz[d];                    bool flag = INRANGE(fx, fy, fz);                    near += flag;                    if(flag && (i + j + k)&1)                        solver.Insert(num[i][j][k], num[fx][fy][fz], 2);                }                ans += near;                if((i + j + k)&1)                    solver.Insert(S, num[i][j][k], near);                else                    solver.Insert(num[i][j][k], T, near);            }    for(int i = 1; i <= m; ++i)        for(int j = 1; j <= m; ++j)            for(int k = 1; k <= m; ++k)                if((i + j + k)&1) {                    if(src[i][j][k] == ‘P‘)                        solver.Insert(S, num[i][j][k], INF);                    else if(src[i][j][k] == ‘N‘)                        solver.Insert(num[i][j][k], T, INF);                }                else {                    if(src[i][j][k] == ‘P‘)                        solver.Insert(num[i][j][k], T, INF);                    else if(src[i][j][k] == ‘N‘)                        solver.Insert(S, num[i][j][k], INF);                }    int max_flow = 0;    while(solver.BFS())        max_flow += solver.Dinic(S, INF);    cout << ans - max_flow << endl;    return 0;}

BZOJ 1976 BeiJing2010組隊 能量魔方 Cube 最小割

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.