bzoj 2960: 跨平面 最小樹形圖 朱-劉演算法
阿新 • • 發佈:2019-02-15
首先用set找出所有的區域,然後對於一條邊在相鄰的區域之間連有向邊,然後新建一個根連向所有點跑朱-劉演算法即可。
AC程式碼如下:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<set> #define ll long long #define N 3005 #define M 30005 using namespace std; int n,m,cnt,tot,fa[N],rch[N],id[N],mrk[N],q[M],blg[M]; bool bo[M]; struct point{ int x,y; }a[N]; struct edg{ int x,y,z; double k; }e[M]; struct cmp{ bool operator()(int x,int y){ return e[x].k<e[y].k; } }; ll crs(point u,point v){ return (ll)u.x*v.y-(ll)u.y*v.x; } set<int,cmp>s[N]; int solve(int rt){ int ans=0,i,j,k; while (1){ for (i=0; i<=n; i++) rch[i]=1000000000; for (i=1; i<=tot; i++) if (e[i].z<rch[e[i].y] && e[i].x!=e[i].y){ rch[e[i].y]=e[i].z; fa[e[i].y]=e[i].x; } cnt=-1; rch[rt]=0; for (i=0; i<=n; i++) id[i]=mrk[i]=-1; for (i=0; i<=n; i++){ ans+=rch[i]; for (k=i; k!=rt && mrk[k]!=i && id[k]==-1; k=fa[k]) mrk[k]=i; if (k!=rt && id[k]==-1){ id[k]=++cnt; for (j=fa[k]; j!=k; j=fa[j]) id[j]=cnt; } } if (cnt==-1) break; for (i=0; i<=n; i++) if (id[i]==-1) id[i]=++cnt; for (i=1; i<=tot; i++){ k=rch[e[i].y]; e[i].x=id[e[i].x]; e[i].y=id[e[i].y]; if (e[i].x!=e[i].y) e[i].z-=k; } n=cnt; rt=id[rt]; } return ans; } int main(){ scanf("%d%d",&n,&m); int i,j,x; for (i=1; i<=n; i++) scanf("%d%d",&a[i].x,&a[i].y); for (i=1; i<=m; i++){ scanf("%d%d%d",&e[i<<1].x,&e[i<<1].y,&e[i<<1].z); e[i<<1|1].x=e[i<<1].y; e[i<<1|1].y=e[i<<1].x; scanf("%d",&e[i<<1|1].z); } for (i=2; i<=(m<<1|1); i++){ e[i].k=-atan2(a[e[i].y].y-a[e[i].x].y,a[e[i].y].x-a[e[i].x].x); s[e[i].x].insert(i); } memset(bo,1,sizeof(bo)); set<int,cmp>::iterator it; ll tmp; int tp; for (i=2; i<=(m<<1|1); i++) if (bo[i]){ tp=1; q[1]=i; while (1){ bo[q[tp]]=0; it=s[e[q[tp]].y].find(q[tp]^1); it++; if (it==s[e[q[tp]].y].end()) it=s[e[q[tp]].y].begin(); if (*it==i) break; else q[++tp]=*it; } tmp=0; for (j=1; j<=tp; j++) tmp+=crs(a[e[q[j]].x],a[e[q[j]].y]); if (tmp>=0){ cnt++; for (j=1; j<=tp; j++) blg[q[j]]=cnt; } } x=1; n=cnt+1; for (i=2; i<=(m<<1|1); i++) if (e[i].z){ tot++; x+=e[i].z; e[tot].z=e[i].z; e[tot].x=blg[i]; e[tot].y=blg[i^1]; } for (i=0; i<n; i++){ tot++; e[tot].x=n; e[tot].y=i; e[tot].z=x; } printf("%d\n",solve(n)-x); return 0; }
by lych
2016.4.14