Go Running(二分图最小点覆盖 网络流 点覆盖)

http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1007&cid=882

题意:

给出一些点,你只能用斜率为1或者-1的线去覆盖。问最少的线的数量。

解析:

把点 ( x i , y i ) (x_i,y_i) (xi,yi)看出边,相连的二分图的两边的点为 ( x i + y i , x i − y i ) (x_i+y_i,x_i-y_i) (xi+yi,xiyi)

也就是说,选择了点 x + y = x i + y i x+y=x_i+y_i x+y=xi+yi或者 x − y = x i − y i x-y=x_i-y_i xy=xiyi都可以覆盖这条边。

最后二分图跑个最大流(时间复杂度为 O ( M l o g N ) O(MlogN) O(MlogN)

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-07-30-13.11.21
 */
#include
using namespace std;
#define LL long long
#define LD long double
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
const int N=2e6+9,M=2e6+9;

int n,m,c;

int head[N],nex[M],to[M],val[M],now;
void add(int a,int b,int v){
    to[++now]=b;val[now]=v;nex[now]=head[a];head[a]=now;
    to[++now]=a;val[now]=0;nex[now]=head[b];head[b]=now;
}

//*********************

int sp,ep,d[N];

int bfs(){
    queue<int>Q;
    memset(d,-1,sizeof(d));
    d[sp]=0;
    Q.push(sp);
    while(!Q.empty()){
        int p=Q.front();Q.pop();
        for(int i=head[p];~i;i=nex[i]){
            int u=to[i];
            if(d[u]==-1&&val[i]>0){
                d[u]=d[p]+1;
                Q.push(u);
            }
        }
    }
    return d[ep]!=-1;
}

int dfs(int p,int v){
    int r=0;
    if(p==ep)return v;
    for(int i=head[p];(~i)&&r<v;i=nex[i]){
        int u=to[i];
        if(val[i]>0&&d[u]==d[p]+1){
            int x=dfs(u,min(val[i],v-r));
            r+=x;
            val[i]-=x;
            val[i^1]+=x;
        }
    }
    if(!r)d[p]=-2;
    return r;
}

int dinic(){
    int ans=0,t;
    while(bfs()){
        while(t=dfs(sp,inf))ans+=t;
    }
    return ans;
}

//***********************

void init(){
    now=-1;//要求第一条边为0
    memset(head,-1,sizeof(head));
}

int t[maxn],x[maxn];
int cnt[maxn<<1];

int main(){
    int _=rd;
    while(_--){
        init();
        int n=rd;
        int now1=0;
        int now2=0;
        unordered_map<int,int>id1;
        unordered_map<int,int>id2;
        sp=2*n+1;
        ep=2*n+2;
        rep(i,1,n){
            t[i]=rd,x[i]=rd;
            int L,R;
            if(id1.count(x[i]+t[i])){
                L=id1[x[i]+t[i]];
            }
            else{
                id1[x[i]+t[i]]=++now1;
                L=now1;
            }

            if(id2.count(x[i]-t[i])){
                R=id2[x[i]-t[i]];
            }
            else{
                id2[x[i]-t[i]]=++now2;
                R=now2;
            }
            add(L,n+R,1);
        }
        rep(i,1,n)add(sp,i,1);
        rep(i,1,n)add(i+n,ep,1);

        int ans=dinic();
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(图论/搜索)