3022 "CQOI2017" 古いボックスC @ - @loj


@説明@

Cは古いプログラマです。

怠惰なプログラマのように、コンピュータ上の時間を殺すために、古いCブロックのゲームをプレイするために使用されます。、R行とC列のグリッドによって裏打ち小さなボックスにゲームの間に定義されている場合、隣接すると言われている共通の小さな正方形の両側、及びいくつかの隣接する小さい正方形一般的な側面ではなく、特別な。
特別な公共側の配置は、強力な法律を持っている必要があります。最初の行の二つの小さな正方形の正面側との間の最初の指定は、特殊なエッジです。次に、正方形の期間の水平方向の特別な側面4時間ごとに、垂直方向に各2つの小さな正方形の期間。すべての奇数列の間で交互に右と奇数行に左から、特別な縁と次の列を有しています。

グリッドR = C = 8、特別な青色ラベル側縁を以下に示します。
まず、行1の間、列1及び2は、特別なエッジを有しています。垂直期間が全て奇数行のうち、2であるため、列1及び2は、特別なエッジを有しています。4奇数行9および10のすべて、第13及び第14、グリッドが十分に大きい場合、列5および特殊エッジのカラム6中の全ての奇数行との間のようにそこ水平期間、なぜなら彼らは特別なエッジの一つです。
すべての奇数列と次の列の間で特別なエッジを有しているため、図3および図4、列7および8特別な側面間の部分もあるので、交互に右、奇数行に左偶数ラインで彼らの特別なエッジ。グリッドの大きなサイズならば、我々はすべての特別なエッジを見つけるために、同じ方法を使用することができます。

各グリッドは、ゲームの最初に小さな牙Gegang良い小さなボックス内に配置することができ、いくつかの小さな正方形は小箱、小さな箱なし他の場所を入れています。
彼はいくつかの小さなボックスは、それが迷惑な配列形状になることが判明した場合、私は(特別な位置も図側に示されている)、図に示す古いパターンCを嫌い、それも何度もした後、治療を放棄することは容易です回転し、また、簡単に古いCの治療を捨て配置された嫌な形状を反転。

捨てられた治療を防ぐために、古いCは、彼が治療を放棄し、かつ迅速に小さなボックスの残りの部分はその形状を嫌い構成しないように、小さな正方形のグリッドの一部を削除していない利点を活用することにしました。しかし、すべてのゲームはいくつかの金貨を取るためにボックスを削除することです、金貨各正方形は多かれ少なかれ不均一に過ごすために必要です。もちろん、私たちは、できるだけ古いCゲームの金を使いたいのですが、少なくとも、どのくらいの金それ?旧C考えるのが面倒、あなたにこの質問を置きます。

入力フォーマット
最初の行のは、Rは、グリッド列Cの行は、n小さな四角は小さな箱を入れて示し、3つの正整数C、Rを有し、N。
次のn行、各行3つの正整数x、Y、Xは、最初の行の列を表し、wはyは少しGeryの小さな正方形の箱に入れ、それを削除コインwをとります。繰り返さない保証、およびグリッドの範囲内です。

出力形式の
出力線は、最小コストのコインの数を表す整数を含んでいます。

サンプル
サンプル入力1
2 2 4
。1 15
。1 6 2
2 1 7
2 2 8
サンプル入力1
。5
サンプル入力2
。3. 7. 3
。1. 1 10
1 2 15
。1 3 10
2 1 10
2 10 2
2 3 10
。3 10 1
の出力例2
15
データ範囲とヒント
1 <= C、R、N <= 10 ^ 5、1 <= W <= 10 ^ 4。

@溶液@

かすか.JPGについての質問の意味。
しかし、2333年の内部画像に有用な情報の完全な事実インチ

列X(x、y)と(X + 1、Y)における行yのいくつかのオプションが存在し、特殊なエッジを有する場合(すなわち、青色側の画像)を、それらの間には、以下からでなければなりませんいずれかを選択します
(1)(この場所はあまりそのコストを削除することを選択し、明らかである)の(x、y)または(X + 1、y)を削除します。
(2)の周りに隣接する3の(X + 1、y)に加えて(x、y)を削除(X - 1、Y)、 (X、Yは、 - 1)、(X、Y + 1)( それらがある場合)が存在します。
(3)隣接する3の周囲(x、y)は(x + 2、y)は、に加えて、(X + 1、Y)を削除し 、(X + 1、Y + 1 - (1 X + 1、Y) )(存在する場合)。

最小カットを考え、追求し、最小コスト「あなたは一種の中にいくつかのオプションから選択しなければなりません」。

特別な配慮と隣接していないエッジのものではなく、隣接する染色カラー通常染色(黒と白の染色、指摘したが、上記染色同じ色の周りの三点(x、y)を挙げます、(X + 1、Y)は、3つの周りには、同じ色ポイントを染色し、(x、y)と(X + 1、Y)ヘテロ点付近)。
白色点も、W前記被写体の容量をシンク;の容量に黒点接続されたソースは、被写体Wに述べました。

たとえX行目及び(X + 1、Y)との間のエッジ一方のy番目の行の存在次に(x、y)は、(x、y)と(X + 1、Y)、分(容量W1、W2 )(それぞれ、2つのセルのコストを除去し)、それらの周りにグリッドの色が何であるかの方向を参照するには、次の(x、y)は黒(x、y)に隣接している場合- >( X + 1、Y)、 そうでない場合は( X + 1、Y) - > (x、y)とします。
次いで、白色点の周縁部に接続され、その隣接ドット、周囲に黒い斑点は、容量INFあります。

でも、これは我々が制限を満たすために必要なことを知ることができます。
私はより速く10 ^ 5よりも実行、および形而上学ことを尋ねた理由を私に聞かないでください。

@acceptedコード@

#include<map>
#include<cstdio>
#include<iostream>
using namespace std;
typedef pair<int, int> pii;
const int MAXN = 100000;
const int MAXV = 2*MAXN;
const int MAXE = 20*MAXV;
const int INF = int(1E9);
const pii d1[] = {make_pair(0, 1), make_pair(0, -1), make_pair(1, 0)};
const pii d2[] = {make_pair(0, 1), make_pair(0, -1), make_pair(-1, 0)};
struct Graph{
    struct edge{
        edge *nxt, *rev;
        int to, cap, flow;
    }edges[MAXE + 5], *adj[MAXV + 5], *ecnt;
    int s, t, d[MAXV + 5], vd[MAXV + 5];
    void init() {ecnt = &edges[0];}
    void addedge(int u, int v, int c) {
        edge *p = (++ecnt), *q = (++ecnt);
        p->to = v, p->cap = c, p->flow = 0;
        p->nxt = adj[u], adj[u] = p;
        q->to = u, q->cap = 0, q->flow = 0;
        q->nxt = adj[v], adj[v] = q;
        p->rev = q, q->rev = p;
//      printf("! %d %d %d\n", u, v, c);
    }
    int aug(int x, int tot) {
        if( x == t ) return tot;
        int sum = 0, mind = t + 1;
        for(edge *p=adj[x];p;p=p->nxt) {
            if( p->cap != p->flow ) {
                if( d[p->to] + 1 == d[x] ) {
                    int del = aug(p->to, min(tot - sum, p->cap - p->flow));
                    p->flow += del, p->rev->flow -= del, sum += del;
                    if( sum == tot || d[s] == t + 1 ) return sum;
                }
                mind = min(mind, d[p->to]);
            }
        }
        if( sum == 0 ) {
            vd[d[x]]--;
            if( vd[d[x]] == 0 ) {
                d[s] = t + 1;
                return sum;
            }
            d[x] = mind + 1;
            vd[d[x]]++;
        }
        return sum;
    }
    int max_flow(int _s, int _t) {
        s = _s, t = _t;
        int flow = 0;
        while( d[s] != t + 1 )
            flow += aug(s, INF);
        return flow;
    }
}G;
map<pii, int>mp;
int C, R, n;
pii p[MAXN + 5]; int w[MAXN + 5];
int func(pii p) {
    if( p.second & 1 ) return (p.first - 1) % 4;
    else return (p.first - 1) % 4 + 4;
}
int main() {
    scanf("%d%d%d", &C, &R, &n), G.init();
    for(int i=1;i<=n;i++)
        scanf("%d%d%d", &p[i].first, &p[i].second, &w[i]), mp[p[i]] = i;
    int s = n + 1, t = n + 2;
    for(int i=1;i<=n;i++) {
        int type = func(p[i]);
        if( type == 4 || type == 3 )
            G.addedge(s, i, w[i]);
        if( type == 5 || type == 2 )
            G.addedge(i, t, w[i]);
        if( type == 0 ) {
            if( mp.count(make_pair(p[i].first + 1, p[i].second)) ) {
                int j = mp[make_pair(p[i].first + 1, p[i].second)];
                G.addedge(i, j, min(w[i], w[j]));
                for(int k=0;k<3;k++)
                    if( mp.count(make_pair(p[j].first + d1[k].first, p[j].second + d1[k].second)) )
                        G.addedge(j, mp[make_pair(p[j].first + d1[k].first, p[j].second + d1[k].second)], INF);
                for(int k=0;k<3;k++)
                    if( mp.count(make_pair(p[i].first + d2[k].first, p[i].second + d2[k].second)) )
                        G.addedge(mp[make_pair(p[i].first + d2[k].first, p[i].second + d2[k].second)], i, INF);
            }
        }
        if( type == 6 ) {
            if( mp.count(make_pair(p[i].first + 1, p[i].second)) ) {
                int j = mp[make_pair(p[i].first + 1, p[i].second)];
                G.addedge(j, i, min(w[i], w[j]));
                for(int k=0;k<3;k++)
                    if( mp.count(make_pair(p[j].first + d1[k].first, p[j].second + d1[k].second)) )
                        G.addedge(mp[make_pair(p[j].first + d1[k].first, p[j].second + d1[k].second)], j, INF);
                for(int k=0;k<3;k++)
                    if( mp.count(make_pair(p[i].first + d2[k].first, p[i].second + d2[k].second)) )
                        G.addedge(i, mp[make_pair(p[i].first + d2[k].first, p[i].second + d2[k].second)], INF);
            }
        }
    }
    printf("%d\n", G.max_flow(s, t));
}

@詳細@

注意してください!それはタイトルがあると言います!最初の列のX列Y!
このカードは、自閉症への問題の意味です。彼はないと思えるサンプルの外観の結果を読んで思いました。

おすすめ

転載: www.cnblogs.com/Tiw-Air-OAO/p/11416627.html