洛谷P2711 小行星
题目描述
星云中有n颗行星,每颗行星的位置是(x,y,z)。每次可以消除一个面(即x,y或z坐标相等)的行星,但是由于时间有限,求消除这些行星的最少次数。
输入格式
第1行为小行星个数n,第2行至第n+1行为xi, yi, zi,描述第i个小行星所在的位置。
输出格式
共1行,为消除所有行星的最少次数。
将方格图的二维转三维
将坐标的x,y,z依次建边
求最大流最小割
#include<bits/stdc++.h> #define re return #define ll long long #define inc(i,l,r) for(int i=l;i<=r;++i) const int inf=2147483647,maxn=5005; using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n,m,ans,s=3001,t=3002; int hd[maxn],k=1,deep[maxn],cur[maxn]; struct node{ int to,nt,flow; }e[800005]; inline void add(int x,int y,int z) { e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].flow=z; e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].flow=0; } inline bool bfs() { inc(i,1,t)deep[i]=0; deep[s]=1; queue<int>q; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=hd[x];i;i=e[i].nt) { int v=e[i].to; if(!deep[v]&&e[i].flow) { deep[v]=deep[x]+1; if(v==t)re 1; q.push(v); } } } re 0; } inline int dfs(int x,int flow) { if(x==t) re flow; int delta=flow; for(int &i=cur[x];i;i=e[i].nt) { int v=e[i].to; if(deep[v]==deep[x]+1&&e[i].flow) { int d=dfs(v,min(e[i].flow,delta)); e[i].flow-=d;e[i^1].flow+=d; delta-=d; if(!delta)re flow; } } re flow-delta; } int main() { int x,y,z; rd(n); inc(i,1,500) { add(i,i+1500,1); add(s,i,inf); } inc(i,501,1000)add(i,i+1500,1); inc(i,1001,1500) { add(i,i+1500,1); add(i+1500,t,inf); } inc(i,1,n) { rd(x),rd(y),rd(z); add(x+1500,y+500,1); add(y+2000,z+1000,1); } while(bfs()) { inc(i,1,t)cur[i]=hd[i]; ans+=dfs(s,inf); } printf("%d",ans); re 0; }