UOJ#57:[WC2013]平面图(最小左转法+点定位)
来源:互联网 发布:学校网上缴费软件 编辑:程序博客网 时间:2024/04/29 18:26
传送门
在一个平面图中有
n 个顶点和m 条直线段,第i 个顶点的坐标为(xi,yi) ,第j 条直线段连接顶点uj 和顶点vj 。权值为hj ,除顶点uj 和vj 外直线段j 不经过其他的顶点。任意两条直线段如果存在公共点,则该公共点一定是一个顶点,此时这两条直线段都会连接这个顶点。对于任意的两个顶点x 和y ,总是可以找到一顶点序列a1,a2,…,ak 使得a1=x,ak=y 且对于任意1≤i<k1≤i<k 满足ai 和ai+1 被一条直线段直接连接。
这m 条直线段将整个平面分成了若干个区域,其中只有一个区域是无穷大的,其余均是有界的,我们称无穷大的区域为禁区。
现在给出q 次询问,每次给定平面中的任意两个不是顶点且分别不在任意一条直线段上的点A 和B ,请画一条曲线连接A 和B ,要求曲线不能经过禁区以及任何顶点,并使得穿过的直线段中权值最大的尽可能小。你需要对每次询问回答这个值最小为多少。
题解:
如果你写过BZOJ1035的
首先最小左转法找出平面,每条边看做平面间的连边,建出
把每个点离线下来做点定位,用扫描线+平衡树。
最后倍增求树上最小值就好了(当然你也可以
#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ char ch=getchar();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();} return i*f;}inline void W(int x){ static int buf[50]; if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;} while(x)buf[++buf[0]]=x%10,x/=10; while(buf[0])putchar(buf[buf[0]--]+'0');}const int Maxn=2e5+50;const double eps=1e-12;inline int sgn(double x){return (x>eps)-(x<-eps);}int n,m,vis[Maxn],tot=1,A[Maxn],B[Maxn],bl[Maxn],Pcnt,ec,anc[Maxn],q,cnt;inline int getanc(int x){return (x==anc[x])?x:(anc[x]=getanc(anc[x]));}struct L{ int a,b,id,val; L(){} L(int a,int b,int id,int val):a(a),b(b),id(id),val(val){}}l[Maxn];struct P{ double x,y; P(double x=0,double y=0):x(x),y(y){} friend inline P operator -(const P &a,const P &b){return P(a.x-b.x,a.y-b.y);} friend inline double operator *(const P &a,const P &b){return a.x*b.y-a.y*b.x;} inline double slope(){return atan2(y,x);}}p[Maxn<<1];struct E{ int a,b,val; E(int a=0,int b=0,int val=0):a(a),b(b),val(val){} friend inline bool operator <(const E &a,const E &b){return a.val<b.val;}}e[Maxn];struct G{ int v[Maxn],nt[Maxn],w[Maxn],g[Maxn],et,dep[Maxn],id[Maxn]; int fa[Maxn][20],mx[Maxn][20],ind; inline void add(int x,int y,int val){nt[++et]=g[x];g[x]=et;v[et]=y;w[et]=val;} inline void dfs(int x,int f=0,int dis=0){ fa[x][0]=f;mx[x][0]=dis;dep[x]=dep[f]+1;id[x]=ind; for(int i=1;i<=18;i++){ fa[x][i]=fa[fa[x][i-1]][i-1]; mx[x][i]=max(mx[fa[x][i-1]][i-1],mx[x][i-1]); } for(int j=g[x];j;j=nt[j])if(v[j]!=f)dfs(v[j],x,w[j]); } inline void up(int &mn,int &x,int d){ for(int i=18;i>=0;i--) if(d&(1<<i))mn=max(mn,mx[x][i]),x=fa[x][i]; } inline int query(int x,int y){ if(id[x]!=id[y])return -1; if(!id[x]||!id[y])return -1; int mn=0; if(dep[x]<dep[y])swap(x,y); if(dep[x]!=dep[y])up(mn,x,dep[x]-dep[y]); if(x==y)return mn; for(int i=18;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ mn=max(mn,max(mx[x][i],mx[y][i])); x=fa[x][i],y=fa[y][i]; } } return max(mn,max(mx[x][0],mx[y][0])); } }gr;struct cp{ inline bool operator ()(const pair<double,int> &a,const pair<double,int> &b){ int t=sgn(a.first-b.first); if(t)return t<0; else return a.second<b.second; }};set< pair<double,int>,cp >g[Maxn];namespace Scanline{int tc,vis[Maxn];struct T{ int a,b,u,id; T(int a=0,int b=0,int u=0,int id=0):a(a),b(b),u(u),id(id){} friend inline bool operator <(const T &a,const T &b){ if(a.a==b.a)return a.u>b.u; if(p[a.a].x!=p[b.a].x)return p[a.a].x<p[b.a].x; return p[a.a].y>p[b.a].y; }}t[Maxn<<1];struct cmp{ inline bool operator ()(const T &a,const T &b){ if(a.a==a.b)return (p[b.b]-p[a.a])*(p[b.a]-p[a.a])<0; if(b.a==b.b)return (p[a.a]-p[b.a])*(p[a.b]-p[b.a])<0; double t1=(p[a.a]-p[b.b])*(p[a.b]-p[b.b]),t2=(p[a.a]-p[b.a])*(p[a.b]-p[b.a]); double t3=(p[b.a]-p[a.a])*(p[b.b]-p[a.a]),t4=(p[b.a]-p[a.b])*(p[b.b]-p[a.b]); return (t1<-eps&&t2<eps)||(t2<-eps&&t1<eps)||(t3>eps&&t4>-eps)||(t4>eps&&t3>-eps); }};set<T,cmp>S_l;int st[Maxn<<1],tp;inline double area(){ double res=0; for(int i=1;i<=tp;i++)res+=p[l[st[i]].a]*p[l[st[i]].b]; return res;}inline int getsuf(int now){ int b=l[now].b,a=l[now].a;double ang=(p[a]-p[b]).slope(); set< pair<double,int> >::iterator it=g[b].lower_bound(make_pair(ang,0)); if(it==g[b].begin())return (--g[b].end())->second; else return (--it)->second;}inline void dfs(int x){ vis[x]=1;int t=l[x].b;st[++tp]=x; int suf=getsuf(x); if(vis[suf]){ t=(area()>0)?(++Pcnt):0; for(;tp>=1;--tp){ bl[st[tp]]=t;x=st[tp]; int a=l[x].a,b=l[x].b; g[a].erase(make_pair((p[b]-p[a]).slope(),st[tp])); } }else dfs(suf);}inline void getarea(){ for(int i=2;i<=tot;i++)if(!vis[i])dfs((tp=0,i)); for(int i=2;i<=tot;i++) if(p[l[i].a].x<p[l[i].b].x){ t[++tc]=T(l[i].a,l[i].b,0,i); t[++tc]=T(l[i].b,l[i].a,2,i); } for(int i=1;i<=q;i++)t[++tc]=T(i*2+n-1,i*2+n-1,1,i),t[++tc]=T(i*2+n,i*2+n,1,i); sort(t+1,t+tc+1); for(int i=1;i<=tc;i++){ if(t[i].u==2)S_l.erase(T(t[i].b,t[i].a,0,0));//,print(); else if(t[i].u==0)S_l.insert(t[i]);//,print(); else{ set<T>::iterator it=S_l.lower_bound(t[i]); if(it==S_l.begin())continue; --it; int s=(t[i].a-n); (s&1?A[(s+1)/2]:B[(s+1)/2])=bl[(it)->id^1]; } }}}int main(){ n=read(),m=read(); for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read(),++cnt; for(int i=1;i<=m;i++){ int x=read(),y=read(),w=read(); ++tot;l[tot]=L(y,x,tot,w); g[y].insert(make_pair((p[x]-p[y]).slope(),tot)); ++tot;l[tot]=L(x,y,tot,w); g[x].insert(make_pair((p[y]-p[x]).slope(),tot)); } q=read(); for(int i=1;i<=q;i++){ ++cnt;scanf("%lf%lf",&p[cnt].x,&p[cnt].y); ++cnt;scanf("%lf%lf",&p[cnt].x,&p[cnt].y); } Scanline::getarea(); for(int i=2;i<=tot;i+=2) if(bl[i]&&bl[i^1])e[++ec]=E(bl[i],bl[i^1],l[i].val); sort(e+1,e+ec+1); for(int i=1;i<=Pcnt;i++)anc[i]=i; for(int i=1;i<=ec;i++){ if(getanc(e[i].a)==getanc(e[i].b))continue; gr.add(e[i].a,e[i].b,e[i].val); gr.add(e[i].b,e[i].a,e[i].val); anc[getanc(e[i].a)]=getanc(e[i].b); } for(int i=1;i<=Pcnt;i++)if(!gr.id[i])++gr.ind,gr.dfs(i); for(int i=1;i<=q;i++)W(gr.query(A[i],B[i])),putchar('\n');}
阅读全文
0 0
- UOJ#57:[WC2013]平面图(最小左转法+点定位)
- BZOJ1035: [ZJOI2008]Risk(最小左转法+点定位)
- [wc2013]平面图
- 平面图的最小割转最短路(点非常多)
- uoj#58. 【WC2013】糖果公园
- UOJ 58 [WC2013]糖果公园
- UOJ 58 BZOJ 3052 [wc2013] 糖果公园
- 平面图ST最小割(hdu 3870)
- hdu 3035 War(平面图最小割)
- 【BZOJ】【P3051】【wc2013】【平面图】【题解】【平面图转对偶图扫描线MST倍增】
- [UOJ]#58. 【WC2013】糖果公园 树上带修改莫队
- poj1129 平面图点着色
- [poj1161]平面图缩点
- HDU3870 Catch the Theves 题解(平面图最小割转最短路)
- 【BZOJ1001】狼抓兔子(BJOI2006)-平面图最小割转最短路
- 网络流(三) 最小割 平面图转对偶图
- HDOJ3035平面图最小割转最短路
- 【NOI2010】海拔【平面图最小割】
- 知识点
- 个人知乎 ##基础二-WEB知识
- FZU
- 知识点
- findViewById的问题和inflate(0方法
- UOJ#57:[WC2013]平面图(最小左转法+点定位)
- 计算并输出100以内所有含7的或7的倍数的数
- 关于学习生活记录的感想总结
- CSDN-markdown编辑器语法——字体、字号与颜色
- 个人知乎 ##基础三-数据库基础
- AB1601串口死机修改
- HDOJ2115 I Love This Game
- 【学习opencv】高斯滤波及其实现
- 如何用vue.js写购物车功能