【Luogu2711】小行星(网络流,最大流)

来源:互联网 发布:json remove key 编辑:程序博客网 时间:2024/04/28 13:19

题面

题目描述

星云中有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这样连边
否则显然是错误的
这样的话y没有任何限制作用
因此连边是x>y>y>z

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<set>#include<map>#include<vector>#include<queue>using namespace std;#define MAX 3000#define MAXL 5000000#define INF 100000000inline int read(){    int x=0,t=1;char ch=getchar();    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();    if(ch=='-')t=-1,ch=getchar();    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();    return x*t;}struct Line{    int v,next,w;}e[MAXL];int h[MAX],cnt;int ans,S,T;int n;inline void Add(int u,int v,int w){    e[cnt]=(Line){v,h[u],w};    h[u]=cnt++;    e[cnt]=(Line){u,h[v],0};    h[v]=cnt++;}int level[MAX],cur[MAX];bool BFS(){    memset(level,0,sizeof(level));    level[S]=1;    queue<int> Q;    Q.push(S);    while(!Q.empty())    {        int u=Q.front();Q.pop();        for(int i=h[u];i!=-1;i=e[i].next)        {            int v=e[i].v;            if(e[i].w&&!level[v])                level[v]=level[u]+1,Q.push(v);        }    }    return level[T];}int DFS(int u,int flow){    if(flow==0||u==T)return flow;    int ret=0;    for(int &i=cur[u];i!=-1;i=e[i].next)    {        int v=e[i].v;        if(e[i].w&&level[v]==level[u]+1)        {            int dd=DFS(v,min(flow,e[i].w));            flow-=dd;ret+=dd;            e[i].w-=dd;e[i^1].w+=dd;        }    }    return ret;}int Dinic(){    int ret=0;    while(BFS())    {        for(int i=S;i<=T;++i)cur[i]=h[i];        ret+=DFS(S,INF);    }    return ret;}int main(){    memset(h,-1,sizeof(h));    n=read();    S=0;T=2001;    for(int i=1;i<=500;++i)Add(S,i,1),Add(i+1500,T,1),Add(i+500,i+1000,1);    for(int i=1;i<=n;++i)    {        int x=read(),y=read(),z=read();        Add(x,y+500,INF);Add(y+1000,z+1500,INF);    }    printf("%d\n",Dinic());    return 0;}
原创粉丝点击