zoukankan      html  css  js  c++  java
  • Go Running【二分图匹配】

    来源

    http://acm.hdu.edu.cn/showproblem.php?pid=6808

    思路

    报告时刻为t,位置为x,那么相同的t+x或者t−x的点能够被一个人(线段)覆盖。
    转化为二分图匹配,选择最少的直线,能够包括所有给定的点。
    离散化后用dinic求最大流,即为原图的最小点覆盖。
    注意maxm要开四倍空间,因为一个点产生两个线段,一个线段需要正反两条边。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    #define dd(x) cout << #x << "=" << x << ","
    #define de(x) cout << #x << "=" << x << endl
    #define rep(i,a,b) for(int i=(a);i<(b);++i)
    #define per(i,a,b) for(int i=(b-1);i>=a;--i)
    #define all(x) (x).begin(),(x).end()
    #define sz(x) (int)(x).size()
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define endl "
    "
    #define lowbit(x) x&(-x)
    #define inf 0x3f3f3f3f
    const int maxn=400010;
    const int maxm=400010;
    
    struct edge{
    	int to,next,cap,flow;
    }edge[maxm];
    int tol;
    int head[maxn];
    void init(){
    	tol = 2;
    	memset(head,-1,sizeof(head));
    }
    void addedge(int u,int v,int w,int rw=0){
    	edge[tol].to=v;
    	edge[tol].cap=w;
    	edge[tol].flow=0;
    	edge[tol].next=head[u];
    	head[u]=tol++;
    	edge[tol].to=u;
    	edge[tol].cap=rw;
    	edge[tol].flow=0;
    	edge[tol].next=head[v];
    	head[v]=tol++;
    }
    int q[maxn];
    int dep[maxn],cur[maxn],sta[maxn];
    bool bfs(int s,int t,int n){
    	int front=0,tail=0;
    	memset(dep,-1,sizeof(dep));
    	dep[s]=0;
    	q[tail++]=s;
    	while (front<tail){
    		int u=q[front++];
    		for (int i=head[u]; i!=-1; i=edge[i].next){
    			int v=edge[i].to;
    			if (edge[i].cap>edge[i].flow && dep[v]==-1){
    				dep[v]=dep[u]+1;
    				if (v==t) return true;
    				q[tail++] = v;
    			}
    		}
    	}
    	return false;
    }
    
    int dinic(int s,int t,int n){
    	int maxflow=0;
    	while (bfs(s,t,n)){
    		for (int i=0; i<n; i++) cur[i]=head[i];
    		int u=s,tail=0;
    		while (cur[s]!=-1){
    			if (u==t){
    				int tp=inf;
    				for (int i=tail-1; i>=0; i--)
    					tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
    				maxflow+=tp;
    				for (int i=tail-1; i>=0; i--){
    					edge[sta[i]].flow+=tp;
    					edge[sta[i]^1].flow-=tp;
    					if (edge[sta[i]].cap-edge[sta[i]].flow==0) 
    						tail=i;
    				}
    				u=edge[sta[tail]^1].to;
    			}
    			else if (cur[u]!=-1 && edge[cur[u]].cap>edge[cur[u]].flow
    			&& dep[u]+1==dep[edge[cur[u]].to]){
    				sta[tail++]=cur[u];
    				u=edge[cur[u]].to;
    			}
    			else{
    				while (u!=s && cur[u]==-1)
    					u=edge[sta[--tail]^1].to;
    				cur[u]=edge[cur[u]].next;
    			}
    		}
    	}
    	return maxflow;
    }
    
    int x[maxn],y[maxn];
    vector<int> V1,V2;
    #define r1(x) lower_bound(all(V1),x)-V1.begin()
    #define r2(x) lower_bound(all(V2),x)-V2.begin()
    
    int main(){
        int T;
        cin>>T;
        while (T--){
        	int n;
        	scanf("%d",&n);
        	V1.clear();
        	V2.clear();
        	for (int i=1; i<=n; i++){
        		scanf("%d%d",&x[i],&y[i]);
        		V1.pb(x[i]+y[i]);
        		V2.pb(x[i]-y[i]);
    		}
    		sort(all(V1));
    		V1.erase(unique(all(V1)),V1.end());
    		sort(all(V2));
    		V2.erase(unique(all(V2)),V2.end());
    		init();
    		int s=sz(V1)+sz(V2),t=s+1;
    		for (int i=1; i<=n; i++)
    			addedge(r1(x[i]+y[i]),sz(V1)+r2(x[i]-y[i]),1);
    		for (int i=0; i<sz(V1); i++)
    			addedge(s,i,1);
    		for (int i=0; i<sz(V2); i++)
    			addedge(sz(V1)+i,t,1);
    //		for (int i=0; i<tol; i++){
    //			cout<<edge[i].cap<<' '<<edge[i].to<<' '<<edge[i].next<<endl;
    //		} 
    		printf("%d
    ",dinic(s,t,sz(V1)+sz(V2)+2));
    	}
        return 0;
    }
    

    参考文献

    [1] https://blog.csdn.net/weixin_43828245/article/details/107700724
    [2] https://blog.csdn.net/qq_43680965/article/details/107700559
    [3] https://blog.csdn.net/weixin_43828245/article/details/107700724
    [4] https://www.cnblogs.com/stelayuri/p/13405914.html

  • 相关阅读:
    Android中得到布局文件对象有三种方式
    android中的键值对
    .length()与.length与.size()
    异常处理
    Python操作Excel
    写一个简单的爬虫(博客)
    开发一个登录接口(Mysql)
    常用模块
    内置函数
    装饰器
  • 原文地址:https://www.cnblogs.com/fzulinxin/p/13636044.html
Copyright © 2011-2022 走看看