4823: [Cqoi2017]老C的方块

很不争气地借用了别人家的题解。。



#include
#include
#include
#include
#include
#include
#include
#include
#define min(a,b) ((a) < (b) ? (a) : (b))
using namespace std;
 
const int INF = ~0U>>1;
const int maxn = 2E5 + 20;
const int maxm = 2E6 + 20;
 
struct E{
    int to,cap,flow; E(){}
    E(int to,int cap,int flow): to(to),cap(cap),flow(flow){}
}edgs[maxm];
 
struct Point{
    int x,y; Point(){}
    Point(int x,int y): x(x),y(y){}
    bool operator < (const Point &B) const
    {
        if (x < B.x) return 1;
        if (x > B.x) return 0;
        return y < B.y;
    }
}p[maxn];
 
int C,R,n,m,s,t,cnt,tot,L[maxn],cur[maxn],w[maxn],A[maxn],B[maxn];
 
queue  Q;
map  M;
vector  v[maxn];
 
inline int getint()
{
    char ch = getchar(); int ret = 0;
    while (ch < '0' || '9' < ch) ch = getchar();
    while ('0' <= ch && ch <= '9')
        ret = ret * 10 + ch - '0',ch = getchar();
    return ret;
}
 
inline void Add(int x,int y,int cap)
{
    v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0);
    v[y].push_back(cnt); edgs[cnt++] = E(x,0,0);
}
 
void Build()
{
    for (int i = 1; i <= n; i++)
    {
        Add(A[i],B[i],w[i]);
        if (p[i].x % 4 == 1 && !(p[i].y & 1))
        {
            Add(s,A[i],INF);
            if (M.count(Point(p[i].x,p[i].y - 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y - 1)]],w[i]);
            if (M.count(Point(p[i].x,p[i].y + 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y + 1)]],w[i]);
            if (M.count(Point(p[i].x - 1,p[i].y)))
                Add(B[i],A[M[Point(p[i].x - 1,p[i].y)]],w[i]);
        }
        else if (p[i].x % 4 == 0 && (p[i].y & 1))
        {
            Add(s,A[i],INF);
            if (M.count(Point(p[i].x,p[i].y - 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y - 1)]],w[i]);
            if (M.count(Point(p[i].x,p[i].y + 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y + 1)]],w[i]);
            if (M.count(Point(p[i].x + 1,p[i].y)))
                Add(B[i],A[M[Point(p[i].x + 1,p[i].y)]],w[i]);
        }
        else if (p[i].x % 4 == 1 && (p[i].y & 1))
        {
            if (M.count(Point(p[i].x + 1,p[i].y)))
                Add(B[i],A[M[Point(p[i].x + 1,p[i].y)]],w[i]);
        }
        else if (p[i].x % 4 == 0 && !(p[i].y & 1))
        {
            if (M.count(Point(p[i].x - 1,p[i].y)))
                Add(B[i],A[M[Point(p[i].x - 1,p[i].y)]],w[i]);
        }
        else if (p[i].x % 4 == 2 && (p[i].y & 1))
        {
            if (M.count(Point(p[i].x + 1,p[i].y)))
                Add(B[i],A[M[Point(p[i].x + 1,p[i].y)]],w[i]);
            if (M.count(Point(p[i].x,p[i].y - 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y - 1)]],w[i]);
            if (M.count(Point(p[i].x,p[i].y + 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y + 1)]],w[i]);
        }
        else if (p[i].x % 4 == 3 && !(p[i].y & 1))
        {
            if (M.count(Point(p[i].x - 1,p[i].y)))
                Add(B[i],A[M[Point(p[i].x - 1,p[i].y)]],w[i]);
            if (M.count(Point(p[i].x,p[i].y - 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y - 1)]],w[i]);
            if (M.count(Point(p[i].x,p[i].y + 1)))
                Add(B[i],A[M[Point(p[i].x,p[i].y + 1)]],w[i]);
        }
        else if ((p[i].x % 4 == 2 && !(p[i].y & 1)) || (p[i].x % 4 == 3 && (p[i].y & 1))) Add(B[i],t,w[i]);
    }
}
 
inline bool BFS()
{
    for (int i = 1; i <= t; i++) L[i] = 0;
    Q.push(s); L[s] = 1;
    while (!Q.empty())
    {
        int k = Q.front(); Q.pop();
        for (int i = 0; i < v[k].size(); i++)
        {
            E e = edgs[v[k][i]];
            if (e.cap == e.flow || L[e.to]) continue;
            L[e.to] = L[k] + 1; Q.push(e.to);
        }
    }
    return L[t];
}
 
inline int Dinic(int x,int a)
{
    if (x == t) return a; int flow = 0;
    for (int &i = cur[x]; i < v[x].size(); i++)
    {
        E &e = edgs[v[x][i]];
        if (e.cap == e.flow || L[e.to] != L[x] + 1) continue;
        int f = Dinic(e.to,min(e.cap - e.flow,a));
        if (!f) continue; flow += f; e.flow += f;
        edgs[v[x][i]^1].flow -= f; a -= f;
        if (!a) return flow;
    }
    if (!flow) L[x] = -1; return flow;
}
 
int main()
{
    #ifdef DMC
        freopen("DMC.txt","r",stdin);
    #endif
     
    C = getint(); R = getint(); n = getint();
    for (int i = 1; i <= n; i++)
    {
        int x = getint(),y;
        y = getint(); w[i] = getint();
        M[p[i] = Point(x,y)] = i;
        A[i] = ++tot; B[i] = ++tot;
    }
     
    s = ++tot; t = ++tot;
    Build(); int MinCut = 0;
    while (BFS())
    {
        for (int i = 1; i <= t; i++) cur[i] = 0;
        MinCut += Dinic(s,INF);
    }
    cout << MinCut << endl;
    return 0;
}


你可能感兴趣的:(网络流,最小割)