• 平面图总结


    转对偶图

    平面图的最小割对应着对偶图的最短路。
    方法:
    首先把每条边拆成双向边。
    然后,把每个点的所有出边按极角进行排序。
    每次:从任意一条未标记的边((u,v))开始,把它标记,并找到v的出边中极角序在((v,u))之后的第一条边。
    直到找到一条被标记的边。
    这时,我们就找到了一个面。通过这种方式,每条边恰好对应一个面。
    一个面周围的所有边的反向边所对应的面,就是这个面的相邻面,在对偶图中建一条边。
    最后,可以根据面积的正负性,找到那个无穷大的面。
    这样,就完成了对偶图的建立。
    代码:

    	int m,k=0;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&X[i],&Y[i]);
    	for(int i=0;i<m;i++)
    	{
    		int a,b,c;
    		scanf("%d%d%d",&a,&b,&c);
    		int za=addl(a,b,c);
    		int zb=addl(b,a,c);
    		tf[a].push_back(zb);
    		tf[b].push_back(za);
    	}
    	for(int i=1;i<=n;i++)
    		sort(ve[i].begin(),ve[i].end());
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<ve[i].size();j++)
    			dy[i][ve[i][j].i]=j;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<ve[i].size();j++)
    			fn[i][j]=dy[ve[i][j].v][tf[i][ve[i][j].i]];
    	}
    	for(int x=1;x<=n;x++)
    	{
    		for(int y=0;y<ve[x].size();y++)
    		{
    			if(bk[x][y])
    				continue;
    			int u=x,v=y,s=0;k+=1;
    			bool zd=false;SVe la;
    			while(!bk[u][v])
    			{
    				bk[u][v]=true;
    				ma[u][v]=k;
    				fflush(stdout);
    				int z=ve[u][v].v,t=(fn[u][v]+1)%ve[z].size();
    				bi[k].push_back(SBi(u,v));
    				SVe e=SPt(X[z],Y[z])-SPt(X[u],Y[u]);
    				if(s>0&&sgn(la*e)<0)
    					zd=true;
    				la=e;u=z;v=t;s+=1;
    			}
    			if(zd)out=k;
    		}
    	}
    	for(int i=1;i<=k;i++)
    		fr[i]=-1;
    	for(int i=1;i<=k;i++)
    	{
    		for(int j=0;j<bi[i].size();j++)
    		{
    			int u=bi[i][j].u,v=bi[i][j].v;
    			int z=ve[u][v].v,t=fn[u][v];
    			addb(i,ma[z][t],ve[u][v].c);
    		}
    	}
    

    点定位

    从该点,作一条平行于y轴的向上的线。
    求出这条射线与图中的边的交点的y坐标的最小值。
    忽略图中平行于y轴的线段。若有多个,取对应的另一个点y坐标最小的那条边。
    这条边所对应的面就是答案。

    若有q组询问,暴力的时间复杂度为(O(nq))
    若支持离线,可以通过扫描线优化至(O((n+q)logn))

    用set维护所有交点,在全局变量中记录当前扫描到的x坐标。
    在比较函数中使用这个变量。

    代码:

    struct SSe
    {
    	int i,j,v;
    	double gety(int x)const
    	{
    		return ::gety(X[i],Y[i],X[v],Y[v],x);
    	}
    	SSe(){}
    	SSe(int I,int J,int V)
    	{
    		i=I;j=J;v=V;
    	}
    };
    bool operator<(const SSe &a,const SSe &b)
    {
    	double ya=a.gety(WX),yb=b.gety(WX);
    	return ya<yb||(sgn(ya-yb)==0&&Y[a.i]<Y[b.i]);
    }
    void solve(int m)
    {
    	multiset<SSe> se;
    	for(int i=0,a=0,b=0;i<m;i++)
    	{
    		while(b<n&&jd[b].x>xw[i].x)
    		{
    			int u=jd[b].i;
    			for(int j=0;j<ve[u].size();j++)
    			{
    				int v=ve[u][j].v;
    				if(X[v]>X[u])
    					se.erase(SSe(v,0,u));
    			}
    			b+=1;
    		}
    		WX=xw[i].x;
    		X[n+1+i]=xw[i].x;Y[n+1+i]=xw[i].y;
    		while(a<n&&jd[a].x>=xw[i].x)
    		{
    			int u=jd[a].i;
    			for(int j=0;j<ve[u].size();j++)
    			{
    				int v=ve[u][j].v;
    				if(X[v]<X[u]&&X[v]<=xw[i].x)
    					se.insert(SSe(u,j,v));
    			}
    			a+=1;
    		}
    		multiset<SSe>::iterator it=se.lower_bound(SSe(0,0,n+1+i));
    		if(it==se.end())
    			ans[xw[i].i]=out;
    		else
    			ans[xw[i].i]=ma[it->i][it->j];
    	}
    }
    
  • 相关阅读:
    git 的安装与初始化
    django的ORM
    elasticsearch基本使用
    给django视图类添加装饰器
    python的编码
    为django项目配置celery的后台启动
    django+celery +rabbitmq
    hadoop安装
    django中间件
    Blockchain For Dummies(IBM Limited Edition
  • 原文地址:https://www.cnblogs.com/lnzwz/p/12819827.html
Copyright © 2020-2023  润新知