zoukankan      html  css  js  c++  java
  • Gym 101221I BZOJ 4080 [WF2014]Sensor Network (二分图匹配)

    题目链接

    (Gym) https://codeforces.com/gym/101221/
    (BZOJ) 大人,时代变了。

    题解

    又是一道看了题解的作业题。
    这是一个最大团(或者补图上的最大独立集)问题,而二分图最大独立集是可以做的,因此可以考虑转化成二分图。
    枚举点集的直径的两端点 (x,y),满足 (dis(x,y)le d),那么剩下点的可选范围就是两个分别以 (x,y) 为圆心、(dis(x,y)) 为半径的圆的交。

    可以发现,以两点连线为界,交的区域被分成了两部分。如果两个点距离大于 (dis(x,y)),那么它们一定位于不同的两部分。
    于是天然的二分图就构建好了!在上面求最大独立集也就是用总点数减去最大匹配即可。
    时间复杂度 (O(n^{4.5})),但是跑得飞快,cf 上只用 (46 ext{ms}).
    另外 lk 的博客上说是 (O(n^4)),但并不知道为什么。

    代码

    #include<bits/stdc++.h>
    #define llong long long
    #define mkpr make_pair
    #define x first
    #define y second
    #define iter iterator
    #define riter reverse_iterator
    #define y1 Lorem_ipsum_
    #define tm dolor_sit_amet_
    using namespace std;
    
    inline int read()
    {
    	int x = 0,f = 1; char ch = getchar();
    	for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    	for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    	return x*f;
    }
    
    namespace NetFlow
    {
    	const int N = 202;
    	const int M = 10200;
    	const int INF = 1e6;
    	struct Edge
    	{
    		int v,w,nxt;
    	} e[(M<<1)+3];
    	int fe[N+3];
    	int te[N+3];
    	int dep[N+3];
    	int que[N+3];
    	int n,en,s,t;
    	void clear()
    	{
    		for(int i=1; i<=n; i++) fe[i] = te[i] = dep[i] = que[i] = 0;
    		for(int i=1; i<=en; i++) e[i].v = e[i].w = e[i].nxt = 0;
    		n = s = t = 0; en = 1;
    	}
    	void addedge(int u,int v,int w)
    	{
    //		printf("addedge %d %d %d
    ",u,v,w);
    		en++; e[en].v = v; e[en].w = w;
    		e[en].nxt = fe[u]; fe[u] = en;
    		en++; e[en].v = u; e[en].w = 0;
    		e[en].nxt = fe[v]; fe[v] = en;
    	}
    	bool bfs()
    	{
    		for(int i=1; i<=n; i++) dep[i] = 0;
    		int head = 1,tail = 1; que[1] = s; dep[s] = 1;
    		while(head<=tail)
    		{
    			int u = que[head]; head++;
    			for(int i=fe[u]; i; i=e[i].nxt)
    			{
    				int v = e[i].v;
    				if(e[i].w>0 && dep[v]==0)
    				{
    					dep[v] = dep[u]+1;
    					if(v==t) return true;
    					tail++; que[tail] = v;
    				}
    			}
    		}
    		return false;
    	}
    	int dfs(int u,int cur)
    	{
    		if(u==t||cur==0) {return cur;}
    		int rst = cur;
    		for(int &i=te[u]; i; i=e[i].nxt)
    		{
    			int v = e[i].v;
    			if(e[i].w>0 && rst>0 && dep[v]==dep[u]+1)
    			{
    				int flow = dfs(v,min(rst,e[i].w));
    				if(flow>0)
    				{
    					e[i].w -= flow;	
    					rst -= flow;
    					e[i^1].w += flow;
    					if(rst==0) {return cur;}
    				}
    			}
    		}
    		if(rst==cur) {dep[u] = -2;}
    		return cur-rst;
    	}
    	int dinic(int _n,int _s,int _t)
    	{
    		n = _n,s = _s,t = _t;
    		int ret = 0;
    		while(bfs())
    		{
    			for(int i=1; i<=n; i++) te[i] = fe[i];
    			memcpy(te,fe,sizeof(int)*(n+1));
    			ret += dfs(s,INF);
    		}
    		return ret;
    	}
    	void dfs2(int u)
    	{
    		dep[u] = 1;
    		for(int i=fe[u]; i; i=e[i].nxt) if(e[i].w>0)
    		{
    			int v = e[i].v; if(dep[v]) continue;
    			dfs2(v);
    		}
    	}
    	void calcway()
    	{
    		for(int i=1; i<=n; i++) dep[i] = 0;
    		dfs2(1);
    	}
    }
    using NetFlow::addedge;
    using NetFlow::dinic;
    
    const int mxN = 100;
    struct Point {int x,y;};
    typedef Point Vector;
    Point operator +(Point x,Point y) {return (Point){x.x+y.x,x.y+y.y};}
    Point operator -(Point x,Point y) {return (Point){x.x-y.x,x.y-y.y};}
    int Norm2(Vector x) {return x.x*x.x+x.y*x.y;}
    int Cross(Vector x,Vector y) {return x.x*y.y-x.y*y.x;}
    
    Point a[mxN+3]; vector<int> way;
    int n; int d;
    
    int main()
    {
    	n = read(),d = read();
    	for(int i=1; i<=n; i++) {a[i].x = read(),a[i].y = read();}
    	int ans = 1; way.push_back(1);
    	for(int x=1; x<=n; x++) for(int y=x+1; y<=n; y++) if(Norm2(a[x]-a[y])<=d*d)
    	{
    		vector<int> s1,s2; int cd = Norm2(a[x]-a[y]);
    		for(int i=1; i<=n; i++) if(i!=x&&i!=y&&Norm2(a[i]-a[x])<=cd&&Norm2(a[i]-a[y])<=cd)
    		{
    			if(Cross(a[y]-a[x],a[i]-a[x])>=0) {s1.push_back(i);} else {s2.push_back(i);}
    		}
    		NetFlow::clear();
    		for(int i=0; i<s1.size(); i++) addedge(1,i+3,1);
    		for(int i=0; i<s2.size(); i++) addedge(i+s1.size()+3,2,1);
    		for(int i=0; i<s1.size(); i++) for(int j=0; j<s2.size(); j++)
    		{
    			if(Norm2(a[s2[j]]-a[s1[i]])>cd) {addedge(i+3,j+s1.size()+3,1);}
    		}
    		int cur = s1.size()+s2.size()-dinic(s1.size()+s2.size()+2,1,2)+2;
    		if(cur>ans)
    		{
    			ans = cur; way.clear(); way.push_back(x),way.push_back(y);
    			NetFlow::calcway();
    			for(int i=0; i<s1.size(); i++) if(NetFlow::dep[i+3]) {way.push_back(s1[i]);}
    			for(int i=0; i<s2.size(); i++) if(!NetFlow::dep[i+s1.size()+3]) {way.push_back(s2[i]);}
    		}
    	}
    	printf("%d
    ",ans);
    	for(int i=0; i<way.size(); i++) printf("%d ",way[i]); puts("");
    	return 0;
    }
    
  • 相关阅读:
    PAT A1094 The Largest Generation (25 分)——树的bfs遍历
    PAT A1055 The World's Richest (25 分)——排序
    PAT A1052 Linked List Sorting (25 分)——链表,排序
    PAT A1076 Forwards on Weibo (30 分)——图的bfs
    辅导员
    辅导员面试
    C程序设计
    Excel VBA 基本概念
    Excel函数
    导入excel表的数据到数据库ssh
  • 原文地址:https://www.cnblogs.com/suncongbo/p/14254669.html
Copyright © 2011-2022 走看看