BZOJ 4823 [Cqoi2017]老C的方块 ——网络流
lrd的题解:http://www.cnblogs.com/liu-runda/p/6695139.html
我还是太菜了。以后遇到这种题目应该分析分析性质的。
网络流复杂度真是$O(玄学)$
#include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define inf 0x3f3f3f3f #define ll long long #define mp make_pair #define maxn 500005 int mov[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; int h[maxn],to[maxn],ne[maxn],fl[maxn],en=0,n,m,k; int S=maxn-2,T=maxn-1,dis[maxn]; queue <int> q; map <pair<int,int>,int> Link; void add(int a,int b,int c) { to[en]=b;ne[en]=h[a];fl[en]=c;h[a]=en++; to[en]=a;ne[en]=h[b];fl[en]=0;h[b]=en++; } bool tell() { memset(dis,-1,sizeof dis); dis[S]=0; q.push(S); while (!q.empty()) { int x=q.front(); q.pop(); for (int i=h[x];i>=0;i=ne[i]) if (dis[to[i]]==-1&&fl[i]>0){ dis[to[i]]=dis[x]+1; q.push(to[i]); } } return dis[T]!=-1; } int zeng(int k,int now) { if (k==T) return now; int ret=0; for (int i=h[k];i>=0&&ret<now;i=ne[i]) if (dis[to[i]]==dis[k]+1&&fl[i]>0) { int tmp=zeng(to[i],min(fl[i],now-ret)); fl[i]-=tmp;fl[i^1]+=tmp;ret+=tmp; } if (!ret) dis[k]=-1; return ret; } int dinic() { int ret=0,tmp; while (tell()) while (tmp=zeng(S,inf)) ret+=tmp; return ret; } int x[maxn],y[maxn],w[maxn]; bool isgreen(int x,int y) { int tmp=(x>>1)&1; if (tmp) return ((x+y)&1); else return (!((x+y)&1)); } bool isblue(int x,int y) {if ((!isgreen(x,y))&&(!((x>>1)&1))) return true;return false;} bool isred(int x,int y) {if ((!isgreen(x,y))&&(!isblue(x,y))) return true;return false;} bool leftgreen(int x,int y) {return (isgreen(x,y))&&(isred(x,y+1))&&(isgreen(x+1,y));} bool rightgreen(int x,int y) {return (isgreen(x,y))&&(isred(x,y+1))&&(isgreen(x-1,y));} void Finout() { freopen("block.in","r",stdin); freopen("block.out","w",stdout); } int main() { memset(h,-1,sizeof h); int n,m,k; scanf("%d%d%d",&n,&m,&k); F(i,1,k) { scanf("%d%d%d",&x[i],&y[i],&w[i]); if (isred(x[i],y[i])) add(S,i,w[i]); else if (isblue(x[i],y[i])) add(i,T,w[i]); Link[mp(x[i],y[i])]=i; } F(i,1,k) { if (isblue(x[i],y[i])) { F(k,0,3) { int tx=x[i]+mov[k][0],tmp,ty=y[i]+mov[k][1]; if (tx>=1&&tx<=n&&ty>=1&&ty<=m&&isgreen(tx,ty)&&(tmp=Link[mp(tx,ty)])) add(tmp,i,inf); } } else if (isred(x[i],y[i])) { F(k,0,3) { int tx=x[i]+mov[k][0],tmp,ty=y[i]+mov[k][1]; if (tx>=1&&tx<=n&&ty>=1&&ty<=m&&isgreen(tx,ty)&&(tmp=Link[mp(tx,ty)])) add(i,tmp,inf); } } else if (leftgreen(x[i],y[i])) { int tmp; if ((tmp=Link[mp(x[i]+1,y[i])])) add(i,Link[mp(x[i]+1,y[i])],min(w[i],w[tmp])); } else if (rightgreen(x[i],y[i])) { int tmp; if ((tmp=Link[mp(x[i]-1,y[i])])) add(i,Link[mp(x[i]-1,y[i])],min(w[i],w[tmp])); } } printf("%d\n",dinic()); }