题目描述 星云中有n颗行星,每颗行星的位置是(x,y,z)。每次可以消除一个面(即x,y或z坐标相等)的行星,但是由于时间有限,求消除这些行星的最少次数。
输入格式 第1行为小行星个数n,第2行至第n+1行为xi, yi, zi,描述第i个小行星所在的位置。
输出格式 共1行,为消除所有行星的最少次数。
输入输出样例 输入 #1复制 3 1 2 3 2 3 1 1 3 2 输出 #1复制 2 说明/提示 1≤n≤50000
1≤x,y,z≤500
很明显的,我们分别对x,y,z分别建图即可。
让x连y,y连z。对y拆点限流。
然后跑最小割,也就是最大流即可。
在大佬那里的图:
AC代码:
#pragma GCC optimize(2) #include<bits/stdc++.h> //#define int long long using namespace std; const int inf=0x3f3f3f3f; const int N=1e4+10,M=1e6+10; int n,s,t,h[N]; int head[N],nex[M],to[M],w[M],tot=1; inline void ade(int a,int b,int c){ to[++tot]=b; w[tot]=c; nex[tot]=head[a]; head[a]=tot; } inline void add(int a,int b,int c){ ade(a,b,c); ade(b,a,0); } inline int bfs(){ queue<int> q; q.push(s); memset(h,0,sizeof h); h[s]=1; while(q.size()){ int u=q.front(); q.pop(); for(int i=head[u];i;i=nex[i]){ if(!h[to[i]]&&w[i]){ h[to[i]]=h[u]+1; q.push(to[i]); } } } return h[t]; } int dfs(int x,int f){ if(x==t) return f; int fl=0; for(int i=head[x];i&&f;i=nex[i]){ if(h[to[i]]==h[x]+1&&w[i]){ int mi=dfs(to[i],min(w[i],f)); w[i]-=mi; w[i^1]+=mi; fl+=mi; f-=mi; } } if(!fl) h[x]=-1; return fl; } int dinic(){ int res=0; while(bfs()) res+=dfs(s,inf); return res; } signed main(){ cin>>n; t=2010; for(int i=1;i<=n;i++){ int x,y,z; scanf("%d %d %d",&x,&y,&z); add(x,y+500,inf); add(y+1000,z+1500,inf); } for(int i=1;i<=500;i++) add(s,i,1),add(i+500,i+1000,1),add(i+1500,t,1); cout<<dinic()<<endl; return 0; }