平面图转对偶图

怎么转对偶图

感性理解,平面图就是没有边相交,可以把每一块面都抠出来的图。它的对偶图就是把面扣出来作为点,有公共边的面之间连边构成的图。关键就是如何抠出面。
把每条无向边拆成两条有向边,每个面都在围成它的有向边的同一侧,这样每条边都用到且仅用到一次。这里我规定每个面在有向边的左侧。每个面逆时针找构成它的边,得到一条边后要找下一条边, 把这条边反向逆时针旋转撞到的第一条就是要找的边。
用vector和atan2实现。找到每条边的下一条边,这些下一条关系构成的所有环就是所有面。再在有公共边的面之间连边即可。
计算每个面的面积,面积为负的即为最外面的无穷大面。

题目

BZOJ1001: [BeiJing2006]狼抓兔子

传送门
平面图最小割等于对偶图最短路,这题不用上面的转法直接就可以搞出对偶图,非常好写了。
多年前的代码了,码风鬼畜啊,还写的spfa,啧啧。

//Achen
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1000+299;
const int N=2*1000*1000+29;
int s,t,n,m,hl[maxn][maxn],sl[maxn][maxn],xl[maxn][maxn],tot;
int fir[N],nxt[N*4],to[N*4],val[N*4],ecnt,vis[N],dis[N],ans,mi1=1e9,mi2=1e9;
void add(int u,int v,int w) {
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
    nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
}
queue<int>que;
void spfa() {
    while(!que.empty()) que.pop();
    memset(vis,0,sizeof(vis));
    memset(dis,127,sizeof(dis));
    dis[s]=0; vis[s]=1;
    que.push(s);
    while(!que.empty()) {
        int now=que.front();
        que.pop(); vis[now]=0;
        for(int i=fir[now];i;i=nxt[i]) {
            if(dis[to[i]]>dis[now]+val[i]) {
                dis[to[i]]=dis[now]+val[i];
                if(!vis[to[i]]) {
                    vis[to[i]]=1;
                    que.push(to[i]);
                } 
             }
           }
    }
}
int main() {
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    while(scanf("%d%d",&n,&m)==2){
    ecnt=0; memset(fir,0,sizeof(fir));
    for(int i=1;i<=n;i++) for(int j=1;j<m;j++) {
    scanf("%d",&hl[i][j]); 
    mi1=min(mi1,hl[i][j]); 
    }
    for(int i=1;i<n;i++) for(int j=1;j<=m;j++) {
    scanf("%d",&sl[i][j]); 
    mi2=min(mi2,sl[i][j]); 
    }
    for(int i=1;i<n;i++) for(int j=1;j<m;j++) scanf("%d",&xl[i][j]);
    s=0; t=(n-1)*(m-1)*2+1;
    for(int i=1;i<n;i++) {
        for(int j=1;j<m;j++) {
            tot++;
            if(j==1) 
                 add(tot,s,sl[i][j]);
            if(i==n-1) 
                add(tot,s,hl[i+1][j]);
            add(tot,tot+1,xl[i][j]);
            tot++;
            if(i==1) 
                add(tot,t,hl[i][j]);
            if(j==m-1) 
                add(tot,t,sl[i][j+1]);
            if(i!=1) 
                add(tot,(i-2)*(m-1)*2+(j-1)*2+1,hl[i][j]);            
            if(j!=m-1) 
                add(tot,tot+1,sl[i][j+1]);
        }
    }
    spfa();
    if(n==1||m==1)  ans=min(mi1,mi2);
    else ans=dis[t];
    printf("%d\n",ans);
    }
    return 0;
}

LOJ#2052. 「HNOI2016」矿区

传送门

吐槽

这题耗了我一下午+一晚上,本机debug n h+本机过后oj上TLE刷评测1h终于过了。。。

血的教训:

e[++ecnt]=edge(u,v,ecnt) = TLE

++ecnt; e[ecnt]=edge(u,v,ecnt) = AC

debug真的是超浪费时间的事情,而且到最后都不知道自己在写什么了,所以要一遍写对呀(臣妾真的做不到啊!)
有时候不知道到底怎么利用时间才是最好的,感觉水了一天和学了一天差别也不是很大,水的时候觉得愧疚别人在学习,学的时候又觉得效率低下还不如后面一排打游戏的人,可能就是因为这样才一直这么菜吧。。

口胡

转成对偶图后,以无穷域为根求这个图的一个生成树,题目要找的块在原图和生成树中都是一个联通块,原图中外围的边若在生成树中仍是生成树中的联通块的外围的边。故找到外围的边中在生成树中的部分就可以得到生成树中的联通块的外围边。对应树中上下边缘的外围边方向是相反的,根据这些外围边的左右边的面的父子关系即可判断是上边缘还是下边缘(上边缘的边左边的面是右边面的儿子,左边的面是联通块上最靠上的点,下边缘的边左边的面是右边面的父亲,左边的面是联通块上最靠下的点,或者反之(画图+感性理解))。
预先求得子树和,得到上下边缘后就可以直接算联通块的和了。
注意判树边的时候,因为有重边,要先判当前边在不在生成树中而不能直接判当前边的两端点是不是父子关系。

自带大常数的丑陋代码

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#define For(i,a,b) for(register int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(register int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=7e5+7;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,q,np[N],istr[N<<1];

template<typename T> void read(T &x) {
    char ch=getchar(); T f=1; x=0;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

#define eps 1e-10
int dcmp(db x) { return fabs(x)<eps?0:(x>0?1:-1); }

struct pt {
	LL x,y;
	pt(){}
	pt(LL x,LL y):x(x),y(y){}
}p[N];
pt operator -(const pt&A,const pt&B) { return pt(A.x-B.x,A.y-B.y); }
LL cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }

int ecnt=1,tid[N<<1];
struct edge {
	int u,v,id; db slop;
	edge(){}
	edge(int u,int v,int id,db slop):u(u),v(v),id(id),slop(slop){}
	friend bool operator <(const edge&A,const edge&B) { 
		return dcmp(A.slop-B.slop)<0||(dcmp(A.slop-B.slop)==0&&A.v<B.v); 
	}
}e[N<<2];

db gslop(int u,int v) {
	return atan2(p[v].y-p[u].y,p[v].x-p[u].x);
}

vector<edge>vc[N];
#define IT vector<edge>::iterator

struct newGraph {
	int ec,rt,fir[N],nxt[N<<1],to[N<<1];
	void add(int u,int v) {
		nxt[++ec]=fir[u]; fir[u]=ec; to[ec]=v;
	}
	
	int f[N],vis[N]; LL sz[N][2];
	void dfs(int x,int fa) {
		f[x]=fa;
		vis[x]=1;
		//printf("%d->%d\n",fa,x);
		for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]) {
			istr[i]=istr[i^1]=1;
			dfs(to[i],x);
			For(j,0,1) sz[x][j]+=sz[to[i]][j];
		}
	}
	
	LL gcd(LL a,LL b) { return !b?a:gcd(b,a%b); }
	
	void solve() {
		//For(i,2,ecnt) printf("%d->%d:%d\n",e[i].u,e[i].v,tid[i]);
		dfs(rt,0);
		//For(i,1,7) printf("%lld\n",sz[i][0]);
		//puts("");
		LL up=0,dn=0;
		For(i,1,q) {
			LL c;
			read(c); c=(c+up)%n+1;
			For(j,1,c) {
				LL x;
				read(x); x=(x+up)%n+1;
				np[j]=x;
			} np[c+1]=np[1];
			up=dn=0;
			For(j,1,c) {
				int x=np[j],y=np[j+1];
				IT it=lower_bound(vc[x].begin(),vc[x].end(),edge(x,y,0,gslop(x,y)));
				int a=(*it).id,b=(a^1);
				if(!istr[a]) continue;
				a=tid[a],b=tid[b];
				if(f[a]==b) {
					dn+=sz[a][0];
					up+=sz[a][1];
				}
				else if(f[b]==a) {
					dn-=sz[b][0];
					up-=sz[b][1];
				}
			}
			up=abs(up); dn=abs(dn);
			LL dd=gcd(up,dn);
			up/=dd; dn/=dd;
			printf("%lld %lld\n",up,dn);
		}
	}
	
}NG;

void add(int u,int v) {
	ecnt++; e[ecnt]=edge(u,v,ecnt,gslop(u,v)); vc[u].push_back(e[ecnt]);	 
	ecnt++; e[ecnt]=edge(v,u,ecnt,gslop(v,u)); vc[v].push_back(e[ecnt]);
}

int nx[N<<1],cnt;
void build() {
	For(i,1,n) sort(vc[i].begin(),vc[i].end());
	For(i,2,ecnt) {
		int v=e[i].v;
		IT it=lower_bound(vc[v].begin(),vc[v].end(),e[e[i].id^1]);
		if(it==vc[v].begin()) it=vc[v].end(); --it;
		nx[i]=(*it).id; 
	}
	For(i,2,ecnt) if(!tid[i]) {
		tid[i]=++cnt;
		LL s=0;
		pt bs=p[e[i].u];
		for(int x=nx[i],pr=i;x!=i;x=nx[x]) {
			tid[x]=cnt;
			pt u=p[e[x].u],v=p[e[x].v];
			s+=cross(u-bs,v-bs);
		}
		if(s<0) NG.rt=cnt;
		else {
			NG.sz[cnt][0]=s*2;
			NG.sz[cnt][1]=s*s;
		}
	}
	NG.ec=1;
	For(i,2,ecnt) NG.add(tid[i],tid[i^1]);
}

int main() {
    //freopen("mine.in","r",stdin);
    //freopen("mine.out","w",stdout);
 	read(n); read(m); read(q);
 	For(i,1,n) {
 		read(p[i].x);
 		read(p[i].y);
 	}
 	For(i,1,m) {
 		int x,y;
 		read(x); read(y);
 		add(x,y);
 	}
 	build();
 	NG.solve();
    Formylove;
}

[WC2013]平面图

传送门
学会转对偶图后就变成代码题了,转成对偶图后求最小生成森林,求两点路径上的最大值即可。
怎么找每个点属于哪个面,离线下来扫描线用set搞一搞,找到我上面的第一条线段。多条线段相交而我又刚好在交点的横坐标的时候似乎不太对啊,于是尝试抖动了一下点然而结果并没有什么改变,不知道是不是被这个卡的。
于是大力码200+行就可以了。
这份代码在luogu上可以过,uoj上被Extra Test卡成97了。。我并不知道怎么改,就先这样吧。
upd:
我睿智了,高度一样比较斜率就好了,然鹅并不是这个被卡的。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<set>
#define For(i,a,b) for(register int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(register int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=2e5+7;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,Q,cnt;

template<typename T> void read(T &x) {
    char ch=getchar(); T f=1; x=0;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

struct Edge {
	int u,v,w;
	friend bool operator <(const Edge&A,const Edge&B) {
		return A.w<B.w;
	}
}ne[N];
int necnt;

int qs[N][2];
struct Newgraph {
	int rt,ec,fir[N],nxt[N],to[N],val[N];
	void add(int u,int v,int w) {
		nxt[++ec]=fir[u]; fir[u]=ec; to[ec]=v; val[ec]=w;
		nxt[++ec]=fir[v]; fir[v]=ec; to[ec]=u; val[ec]=w;
	}
	
	int fa[N];
	int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); }
	
	void kruskal() {
		sort(ne+1,ne+necnt+1);
		For(i,1,cnt) fa[i]=i;
		For(i,1,necnt) {
			int u=ne[i].u,v=ne[i].v,w=ne[i].w;
			if(u==rt||v==rt) continue;
			if(find(u)!=find(v)) {
				fa[find(u)]=find(v);
				add(u,v,w);
			}
		}
	}
	
	int f[N][18],g[N][18],R[N];
	int lca(int x,int y) {
		if(x==y) return 0;
		int rs=0;
		if(R[x]<R[y]) swap(x,y);
		Rep(i,17,0) if(R[f[x][i]]>=R[y]) {
			rs=max(rs,g[x][i]);
			x=f[x][i];
		}
		if(x==y) return rs;
		Rep(i,17,0) if(f[x][i]!=f[y][i]) {
			rs=max(rs,max(g[x][i],g[y][i]));
			x=f[x][i]; y=f[y][i];
		}
		return max(rs,max(g[x][0],g[y][0]));
	}
	
	int itrt[N];
	void dfs(int x,int Fa) {
		f[x][0]=Fa;
		R[x]=R[Fa]+1;
		itrt[x]=itrt[Fa];
		For(i,1,17) {
			f[x][i]=f[f[x][i-1]][i-1];
			g[x][i]=max(g[x][i-1],g[f[x][i-1]][i-1]);
		}
		for(int i=fir[x];i;i=nxt[i]) if(to[i]!=Fa) {
			g[to[i]][0]=val[i];
			dfs(to[i],x);
		}
	}
	
	void solve() {
		kruskal();
		For(i,1,cnt) if(i!=rt&&!itrt[i]) {
			itrt[0]=i; dfs(i,0);
		}
		For(i,1,Q) {
			int x=qs[i][0],y=qs[i][1];
			if(x==rt||y==rt||itrt[x]!=itrt[y]) puts("-1");
			else printf("%d\n",lca(x,y));
		}
	}
}NG;

#define eps 1.0e-8
int dcmp(db x) { return fabs(x)<eps?0:(x>0?1:-1); }

struct pt {
	db x,y;
	pt(){}
	pt(db x,db y):x(x),y(y){}
}p[N],q[N][2];
pt operator -(const pt&A,const pt&B) { return pt(A.x-B.x,A.y-B.y); }
db cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }

int ecnt=1,tid[N];
struct edge {
	int u,v,id,val; db slop;
	edge(){}
	edge(int u,int v,int id,int val,db slop):u(u),v(v),id(id),val(val),slop(slop){}
	friend bool operator <(const edge&A,const edge&B) { 
		return dcmp(A.slop-B.slop)<0||(dcmp(A.slop-B.slop)==0&&A.v<B.v); 
	}
}e[N];

db gslop(int u,int v) {
	return atan2(p[v].y-p[u].y,p[v].x-p[u].x);
}

vector<edge>vc[N];
#define IT vector<edge>::iterator

void add(int u,int v,int w) {
	ecnt++; e[ecnt]=edge(u,v,ecnt,w,gslop(u,v)); vc[u].push_back(e[ecnt]);	 
	ecnt++; e[ecnt]=edge(v,u,ecnt,w,gslop(v,u)); vc[v].push_back(e[ecnt]);
}

int nx[N<<1];
void build() {
	For(i,1,n) sort(vc[i].begin(),vc[i].end());
	For(i,2,ecnt) { 
		int v=e[i].v;
		IT it=lower_bound(vc[v].begin(),vc[v].end(),e[e[i].id^1]);
		if(it==vc[v].begin()) it=vc[v].end(); --it;
		nx[i]=(*it).id; 
	}
	//For(i,2,ecnt) printf("[%d %d]->[%d %d]\n",e[i].u,e[i].v,e[nx[i]].u,e[nx[i]].v);
	For(i,2,ecnt) if(!tid[i]) {
		tid[i]=++cnt;
		db s=0;
		pt bs=p[e[i].u];
		for(int x=nx[i],pr=i;x!=i;x=nx[x]) {
			tid[x]=cnt;
			pt u=p[e[x].u],v=p[e[x].v];
			s+=cross(u-bs,v-bs);
		}
		if(dcmp(s)<0) NG.rt=cnt;
	}
	//For(i,2,ecnt) printf("[%d %d] : %d\n",e[i].u,e[i].v,tid[i]);
	for(int i=2;i<=ecnt;i+=2) 
		ne[++necnt]=(Edge){tid[i],tid[i^1],e[i].val};
}

db Rand() { return (rand()/(db)RAND_MAX-0.5)*eps; }

struct node {
	db x,y; int id,j;
	friend bool operator <(const node&A,const node&B) {
		return A.x<B.x||(A.x==B.x&&A.y<B.y);
	}
	void shake() { x+=Rand(); y+=Rand(); }
}nd[N];

db D;
struct insE {
	int u,v,id;
	friend bool operator <(const insE&A,const insE&B) { 
		db HA=(db)p[A.u].y+(p[A.v].y-p[A.u].y)*(D-p[A.u].x)/((db)(p[A.v].x-p[A.u].x));
		db HB=(db)p[B.u].y+(p[B.v].y-p[B.u].y)*(D-p[B.u].x)/((db)(p[B.v].x-p[B.u].x));
		return HA<HB||(HA==HB&&gslop(A.u,A.v)<gslop(B.u,B.v));
	}
}e2[N];
set<insE>ins;
#define ITs set<insE>::iterator 

struct delE {
	int u,v,id;
	friend bool operator <(const delE&A,const delE&B) { 
		return p[A.v].x<p[B.v].x||(p[A.v].x==p[B.v].x&&A.id<B.id);
	}
};
set<delE>del;

bool cmp(const insE&A,const insE&B) {
	return p[A.u].x<p[B.u].x||(p[A.u].x==p[B.u].x&&p[A.v].x<p[B.v].x);
}
	
void pre() {
	read(Q);
	For(i,1,Q) {
		db Ax,Ay,Bx,By;
		scanf("%lf%lf%lf%lf",&Ax,&Ay,&Bx,&By);
		nd[i]=(node){Ax,Ay,i,0}; nd[i].shake();
		nd[i+Q]=(node){Bx,By,i,1}; //nd[i+Q].shake();
	}
	sort(nd+1,nd+Q*2+1);
	sort(e2+1,e2+m+1,cmp);
	int j=1;
	For(i,1,2*Q) {
		while(del.size()>0) {
			delE t=*del.begin();
			if(dcmp(p[t.v].x-nd[i].x)>=0) break;
			ins.erase((insE){t.u,t.v,t.id});
			del.erase(t);
		}
		D=nd[i].x;
		while(j<=m&&p[e2[j].u].x<=nd[i].x) {
			if(p[e2[j].v].x>=nd[i].x) {
				ins.insert(e2[j]);
				del.insert((delE){e2[j].u,e2[j].v,e2[j].id});
			}
			j++;
		}
		p[n+1]=pt(nd[i].x-1,nd[i].y); p[n+2]=pt(nd[i].x+1,nd[i].y);
		insE t=(insE){n+1,n+2,ecnt+1};
		ITs it=ins.lower_bound(t);
		if(it==ins.end()) qs[nd[i].id][nd[i].j]=NG.rt;
		else qs[nd[i].id][nd[i].j]=tid[((*it).id)^1];
	}
}

int main() {
    //freopen("1.in","r",stdin);
    //freopen("mine.out","w",stdout);
    read(n); read(m);
    For(i,1,n) { read(p[i].x); read(p[i].y); }
    For(i,1,m) {
    	int x,y,z;
    	read(x); read(y); read(z);
    	add(x,y,z);
    	if(p[y].x<p[x].x) e2[i]=(insE){y,x,ecnt};
    	else e2[i]=(insE){x,y,ecnt-1};
    }
    build();
    pre();
    NG.solve();
    Formylove;
}

bzoj2965: 保护古迹

传送门
前面操作和上道题一模一样,最后枚举保护哪些古迹求最小割即对偶图最短路即可。
哪天没事来写。
upd:
发现我在扯淡,求的是对偶图最小割而不是平面图最小割所以还是要跑网络流。。于是写到一半写不下去了。。弃题了。。省选遇到傻逼码农题就打个暴力算了,反正也没几个人能打出来,能打出来的也不是我的目标对手了。。去年联赛和省选和组队打acm的时候不都是因为太相信自己的码力然后爆蛋了然后滚粗嘛。。今年码力似乎也没提高多少,就不要考场指望打出这种题了。。
写了一半的代码

//Achen
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=307;
typedef long long LL;
typedef double db;
using namespace std;
int pcnt,n,m;

template<typename T> void read(T &x) {
	char ch=getchar(); T f=1; x=0;
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-') f=-1,ch=getchar();
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

#define eps 1e-12
int dcmp(db x) { return fabs(x)<eps?0:(x>0?1:-1); } 

struct pt{
	db x,y;
	void read() { scanf("%lf%lf",&x,&y); }
	friend bool operator <(const pt&A,const pt&B) { return A.x<B.x; }
}gj[N],dd[N];
pt operator -(const pt&A,const pt&B) { return (pt){A.x-B.x,A.y-B.y}; }
db cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }
db dot(pt A,pt B) { return A.x*B.x+A.y*B.y; }
db lenth(pt A) { return sqrt(dot(A,A)); }
db get(int u,int v) { return atan2(dd[v].y-dd[u].y,dd[v].x-dd[u].x);}

db nowx;
struct edge{
	int u,v,w,id; db slop;
	friend bool operator <(const edge&A,const edge&B) {
		return dcmp(A.slop-B.slop)<0||(dcmp(A.slop-B.slop)==0&&A.v<B.v);
	}
}e[N<<1],te[N<<1];
int ecnt=1;
vector<edge>vc[N];
#define IT vector<edge>::iterator
void add(int u,int v,int w) {
	++ecnt; e[ecnt]=(edge){u,v,w,ecnt,get(u,v)}; vc[u].push_back(e[ecnt]);
	++ecnt; e[ecnt]=(edge){v,u,w,ecnt,get(v,u)}; vc[v].push_back(e[ecnt]);
}
 
int ec,fir[N];
struct fedge {
	int u,v,cap,fl,nx;
}fe[N<<1];
void ADD(int u,int v,int w) {
	fe[++ec]=(fedge){u,v,w,0,fir[u]}; fir[u]=ec;
	fe[++ec]=(fedge){v,u,0,0,fir[v]}; fir[v]=ec;
}

int enx[N],bl[N],tot,gid[N];
void build() {
	For(i,1,n) sort(vc[i].begin(),vc[i].end());
	For(i,2,ecnt) {
		int u=e[i].u,v=e[i].v;
		IT it=lower_bound(vc[v].begin(),vc[v].end(),e[i^1]);
		if(it==vc[v].begin()) it=vc[v].end(); --it;
		enx[i]=(*it).id;
	}
	For(i,2,ecnt) if(!bl[i]) {
		bl[i]=++tot;
		for(int j=enx[i];j!=i;j=enx[j]) bl[j]=tot;
	}
	For(i,2,ecnt) 
		ADD(bl[i],bl[i^1],e[i].w);
}

struct insE { 
	int id;
	friend bool operator <(const insE&A,const insE&B) {
		int au=e[A.id].u,av=e[A.id].v,bu=e[B.id].u,bv=e[B.id].v;
		db aa=dd[au].y+(dd[av].y-dd[au].y)*(nowx-dd[au].x)/(dd[av].x-dd[au].x);
		db bb=dd[bu].y+(dd[bv].y-dd[bu].y)*(nowx-dd[bu].x)/(dd[bv].x-dd[bu].x);
		return dcmp(aa-bb)<0||(dcmp(aa-bb)==0&&dcmp(e[A.id].slop-e[B.id].slop)<0);
	}
}IE[N];
bool Icmp(const insE&A,const insE&B) { return dd[e[A.id].u].x<dd[e[B.id].u].x; }
struct delE { 
	int id; 
	friend bool operator <(const delE&A,const delE&B) { 
		return dd[e[A.id].v].x<dd[e[B.id].v].x;
	}
};
set<insE>si;
set<delE>sd;

void get_gj() {
	int cc=0,nc=0;
	For(i,2,ecnt) if(dd[e[i].u].x<dd[e[i].v].x) 
		IE[++cc]=(insE){i};
	sort(IE+1,IE+cc+1,Icmp);
	sort(gj+1,gj+pcnt+1);
	For(i,1,pcnt) {
		while(!sd.empty()) {
			delE t=*sd.begin();
			if(dd[e[t.id].v].x<gj[i].x) {
				sd.erase(sd.begin());
				si.erase(si.find((insE){t.id}));
			} else break;
		}
		nowx=gj[i].x;
		while(nc<cc) {
			edge ne=e[IE[nc+1].id];
			if(dd[ne.u].x<=gj[i].x) {
				++nc;
				if(dd[ne.v].x>=gj[i].x) {
					si.insert(IE[nc]);
					sd.insert((delE){IE[nc].id});
				}
			} else break;
		}
		dd[n+1]=(pt){nowx-1,gj[i].y}; dd[n+2]=(pt){nowx+1,gj[i].y};
		e[ecnt+1]=(edge){n+1,n+2};
		set<insE>::iterator it=si.lower_bound((insE){ecnt+1});
		gid[i]=bl[(*it).id^1];
	}
}

void solve() {
	get_gj();
	int s=tot+1,t=tot+2;
	For(s,1,(1<<pcnt)-1) {
		
	}
}

int main() {
    freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
  	read(pcnt); read(n); read(m);
	For(i,1,pcnt) gj[i].read();
	For(i,1,n) dd[i].read();
	For(i,1,m) {
		int u,v,w;
		read(u); read(v); read(w);
		add(u,v,w);
	}
	build();
	solve(); 
	Formylove;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值