zoukankan      html  css  js  c++  java
  • BZOJ2960: 跨平面

    从一条边出发遍历,每次找旋转角度最小的一条边作为下一条边,直到回到出发的边,就得到了一个区域。这样建出对偶图后跑不定根的最小树形图就行了。

    #include<cstdio>
    #include<cmath>
    #include<map>
    #define ub upper_bound
    using namespace std;
    const int N=5005;
    map<double,int>s[N];
    int sum,n,m,q[N],v[N];
    struct edge{
    	int v,w;
    	edge*s;
    }e[N*2];
    edge*l=e,*h[N];
    void add(int u,int v,int w){
    	sum+=w;
    	edge s={v,w,h[u]};
    	*(h[u]=l++)=s;
    }
    struct vec{
    	int x,y;
    	double a;
    	vec(){}
    	vec(int x,int y):x(x),y(y),a(atan2(y,x)){}
    }a[N];
    vec operator-(vec a,vec b){
    	return vec(a.x-b.x,a.y-b.y);
    }
    namespace dual{
    	struct edge{
    		int u,v,w;
    	}e[N*2];
    	edge*l=e;
    	void add(int u,int v,int w){
    		edge s={u,v,w};
    		*l++=s;
    	}
    	int d[N],p[N],s[N],t[N];
    	int find(int&v){
    		for(int i=1;i!=n;++i){
    			s[i]=0;
    			d[i]=1e9;
    		}
    		for(edge*i=e;i!=l;++i)
    			if(d[i->v]>i->w){
    				p[i->v]=i->u;
    				d[i->v]=i->w;
    			}
    		int now=0;
    		for(int i=1;i!=n;++i){
    			v+=d[i];
    			int u=i;
    			for(;u&&!s[u];u=p[u])
    				s[u]=i;
    			now+=s[u]==i;
    			for(;s[u]==i;u=p[u]){
    				s[u]=-1;
    				t[u]=now;
    			}
    		}
    		return now;
    	}
    	int sol(int v){
    		while(int now=find(v)){
    			for(int i=1;i!=n;++i)
    				if(~s[i])t[i]=++now;
    			n=now+1;
    			edge*q=l;
    			for(edge*i=l=e;i!=q;++i)
    				if(t[i->u]!=t[i->v])
    					add(t[i->u],t[i->v],i->w-d[i->v]);
    		}
    		return v;
    	}
    }
    struct buf{
    	char z[1<<20],*s;
    	buf():s(z){
    		z[fread(z,1,sizeof z,stdin)]=0;
    	}
    	operator int(){
    		int x=0,y=0;
    		while(*s<48)
    			if(*s++==45)y=1;
    		while(*s>32)
    			x=x*10+*s++-48;
    		return y?-x:x;
    	}
    }it;
    int sol(){
    	for(int i=1;i<=n;++i)
    		for(edge*j=h[i];j;j=j->s)
    			s[i][(a[j->v]-a[i]).a]=j-e;
    	for(int i=1;i<=n;++i)
    		for(edge*j=h[i];j;j=j->s){
    			typeof(s->end())u=s[j->v].ub((a[i]-a[j->v]).a);
    			if(s[j->v].end()==u)
    				u=s[j->v].begin();
    			q[j-e]=u->second;
    		}
    	using dual::add;
    	using dual::sol;
    	int&now=n=1;
    	for(edge*i=e;i!=l;++i)
    		if(!v[i-e]){
    			for(int j=i-e;!v[j];j=q[j])
    				v[j]=now;
    			add(0,now++,sum);
    		}
    	for(edge*i=e;i!=l;++i)
    		if(i->w)
    			add(v[i-e^1],v[i-e],i->w);
    	return sol(-sum);
    }
    int main(){
    	n=it,m=it;
    	for(int i=1;i<=n;++i){
    		a[i].x=it;
    		a[i].y=it;
    	}
    	while(m--){
    		int s=it,t=it;
    		add(s,t,it);
    		add(t,s,it);
    	}
    	printf("%d
    ",sol());
    }
    
  • 相关阅读:
    快速幂 --- CSU 1556: Jerry's trouble
    iOS masonry 不规则tagView布局 并自适应高度
    iOS 渐变色实现,渐变色圆环,圆环进度条
    iOS scrollView中嵌套多个tableView处理方案
    iOS 多网络请求同步并发
    iOS UIView添加阴影
    什么是比特币,什么是区块链,什么是挖矿,为什么要挖?关于比特币,关于区块链,你想要知道的
    Xcode wifi连接真机调试
    iOS 添加WKWebView导致控制器无法释放的问题
    解决百度网盘非会员下载速度限制的完整方案
  • 原文地址:https://www.cnblogs.com/f321dd/p/5496229.html
Copyright © 2011-2022 走看看