BZOJ 4823:[Cqoi2017]古いボックスの最小カットC

タイトル

BZOJ 4823
LUOGU 3756
説明

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は、考えることをわざわざあなたにこの質問を置きます

入力

最初の行は、3つの正整数C、Rを有し、nは、Rは、グリッド列Cの行は、n小さな四角は小さな箱を入れている意味します。
次のn行、各行3つの正整数x、Y、Xは、最初の行の列を表し、wはyは少しGeryの小さな正方形の箱に入れ、それを削除コインwをとります。保証はしないように
繰り返し、グリッドの範囲内です。\(1≤C、R、 N≤≤10 ^ 5 W 1 ^ 4 \ 10≤)

出力

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

サンプル入力

2 2 4
1 5
1 6 2
2 1 7
2 2 8

サンプル出力

図5は、
図示のように、2×2のグリッド、各小箱は、小さな箱を入れて、除去されたコインの数は、図に示すラベルを取り込みます。この4つの小さな正方形は、正確には、明らかにこれを除去することができない、古いC厄介なグラフィックブロックの残りの部分を形成する5枚のコインを取り、除去される厄介な古いCグラフィック、最初の行の列1の小箱を構成しますプログラムは、金の最小値をとります。

分析

厄介な形状のそれぞれは、偶数うち、ボックスの両側縁のそれぞれに特別なブロックとみなすことができ、注目することができます。
図に示すように、我々は、4つのカテゴリに分類グリッドを置きます。
ここに画像を挿入説明
各厄介な形状は、ブラック→黄色→赤色→緑色として見ることができます。したがって、4層は、ライン上で実行されている図最小カットを構築しました。

コード

私は、一晩この曲を記念ほぼ支払った\(1.5 \)手残留コードのバージョンを

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
const int maxn=1e5+10,maxm=1e6+10,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],head[maxn],len=1;
inline void add(int x,int y,int z)
{
    ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
    ver[++len]=x,edge[len]=0,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn];
inline bool bfs()
{
    queue<int>q;
    memset(dist,0,sizeof(dist));
    q.push(s);dist[s]=1;//天啊,我怎么会少打了dist[s]=1,害我调了这一个晚上
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        for (int i=head[x]; i; i=Next[i])
        {
            int y=ver[i];
            if (edge[i] && !dist[y])
            {
                dist[y]=dist[x]+1;
                if (y==t) return 1;
                q.push(y);
            }
        }
    }
    return 0;
}

inline int get(int x,int low)
{
    if (x==t) return low;
    int tmp=low;
    for (int i=head[x]; i; i=Next[i])
    {
        int y=ver[i];
        if (edge[i] && dist[y]==dist[x]+1)
        {
            int a=get(y,min(tmp,edge[i]));
            if (!a) dist[y]=0;
            edge[i]-=a;
            edge[i^1]+=a;
            if (!(tmp-=a)) break;
        }
    }
    return low-tmp;
}

map<pair<int,int>,int>id;
int a[maxn],b[maxn],w[maxn];
int main()
{
    int c,r,n,x;
    read(c);read(r);read(n);
    s=0,t=n+1;
    for (int i=1; i<=n; ++i) read(a[i]),read(b[i]),read(w[i]),id[mp(a[i],b[i])]=i;//map真好用,怪不得qy一直推崇map
    for (int i=1; i<=n; ++i)
        switch (a[i]%4)
        {
            case 0:
                if (b[i]&1) add(s,i,w[i]);
                else
                {
                    if (id.count(mp(a[i]+1,b[i]))) add(id[mp(a[i]+1,b[i])],i,inf);
                    if (id.count(mp(a[i],b[i]+1))) add(id[mp(a[i],b[i]+1)],i,inf);
                    if (id.count(mp(a[i],b[i]-1))) add(id[mp(a[i],b[i]-1)],i,inf);
                }
                break;
            case 1:
                if (b[i]&1)
                {
                    if (id.count(mp(a[i]-1,b[i]))) add(id[mp(a[i]-1,b[i])],i,inf);
                    if (id.count(mp(a[i],b[i]+1))) add(id[mp(a[i],b[i]+1)],i,inf);
                    if (id.count(mp(a[i],b[i]-1))) add(id[mp(a[i],b[i]-1)],i,inf);
                    if (id.count(mp(a[i]+1,b[i]))) x=id[mp(a[i]+1,b[i])],add(i,x,min(w[i],w[x]));
                }
                else add(s,i,w[i]);
                break;
            case 2:
                if (b[i]&1)
                {
                    if (id.count(mp(a[i]+1,b[i]))) add(i,id[mp(a[i]+1,b[i])],inf);
                    if (id.count(mp(a[i],b[i]+1))) add(i,id[mp(a[i],b[i]+1)],inf);
                    if (id.count(mp(a[i],b[i]-1))) add(i,id[mp(a[i],b[i]-1)],inf);
                }
                else add(i,t,w[i]);
                break;
            case 3: //把3写成4,我真是人才
                if (b[i]&1) add(i,t,w[i]);
                else
                {
                    if (id.count(mp(a[i]-1,b[i]))) add(i,id[mp(a[i]-1,b[i])],inf);
                    if (id.count(mp(a[i],b[i]+1))) add(i,id[mp(a[i],b[i]+1)],inf);
                    if (id.count(mp(a[i],b[i]-1))) add(i,id[mp(a[i],b[i]-1)],inf);
                    if (id.count(mp(a[i]+1,b[i]))) x=id[mp(a[i]+1,b[i])],add(x,i,min(w[i],w[x]));
                }
                break;
        }
    int ans=0;
    while (bfs()) ans+=get(s,inf);
    write(ans),puts("");
    return 0;
}

おすすめ

転載: www.cnblogs.com/G-hsm/p/11323338.html