标签:
平面图求域之后增加超级根,然后建图求最小树形图即可。
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=3010,M=10010,inf=0x7fffffff;
int n,m,q,cnt,i,x,y,z1,z2;
struct P{
int x,y;
P(){}
P(int _x,int _y){x=_x,y=_y;}
ll operator*(const P&b){return 1LL*x*b.y-1LL*y*b.x;}
}a[N],b[M];
struct E{
int x,y,z;double o;
E(){}
E(int _x,int _y,int _z){x=_x,y=_y,z=_z,o=atan2(a[y].x-a[x].x,a[y].y-a[x].y);}
}e[M];
bool del[M];int from[M];
namespace GetArea{
struct cmp{bool operator()(int a,int b){return e[a].o<e[b].o;}};
set<int,cmp>g[N];set<int,cmp>::iterator k;int i,j,q[M],t;
void work(){
for(i=0;i<m+m;i++)if(!del[i]){
for(q[t=1]=j=i;;q[++t]=j=*k){
k=g[e[j].y].find(j^1);k++;
if(k==g[e[j].y].end())k=g[e[j].y].begin();
if(*k==i)break;
}
ll s=0;
for(j=1;j<=t;j++)s+=a[e[q[j]].x]*a[e[q[j]].y],del[q[j]]=1;
if(s<0)continue;
for(cnt++,j=1;j<=t;j++)from[q[j]]=cnt;
}
}
}
namespace DMST{
int n,size,pre[N],id[N],vis[N],in[N];
struct EDGE{
int u,v,cost;
EDGE(){}
EDGE(int a,int b,int c):u(a),v(b),cost(c){}
}E[M];
void init(int _n){n=_n,size=0;}
void add(int u,int v,int w){E[size++]=EDGE(u,v,w);}
int dmst(int root){
int u,v,cnt,ret=0,i;
while(1){
for(i=0;i<n;i++)in[i]=inf;
for(i=0;i<size;i++){
u=E[i].u,v=E[i].v;
if(E[i].cost<in[v]&&u!=v)pre[v]=u,in[v]=E[i].cost;
}
for(cnt=in[root]=i=0;i<n;i++)id[i]=vis[i]=-1;
for(i=0;i<n;i++){
ret+=in[i],v=i;
while(vis[v]!=i&&id[v]==-1&&v!=root)vis[v]=i,v=pre[v];
if(v!=root&&id[v]==-1){
for(u=pre[v];u!=v;u=pre[u])id[u]=cnt;
id[v]=cnt++;
}
}
if(!cnt)break;
for(i=0;i<n;i++)if(id[i]==-1)id[i]=cnt++;
for(i=0;v=E[i].v,i<size;i++){
E[i].u=id[E[i].u],E[i].v=id[E[i].v];
if(E[i].u!=E[i].v)E[i].cost-=in[v];
}
n=cnt,root=id[root];
}
return ret;
}
void work(int _n){
n=_n;
int i,tot=1;
for(i=0;i<m+m;i++)if(e[i].z)add(from[i],from[i^1],e[i].z),tot+=e[i].z;
for(i=0;i<n-1;i++)add(n-1,i,tot);
printf("%d",dmst(n-1)-tot);
}
}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d%d",&x,&y);
a[i]=P(x,y);
}
for(i=0;i<m;i++){
scanf("%d%d%d%d",&x,&y,&z1,&z2);
e[i<<1]=E(x,y,z1);
e[i<<1|1]=E(y,x,z2);
}
for(i=0;i<m+m;i++)GetArea::g[e[i].x].insert(i);
GetArea::work();
DMST::work(cnt+2);
return 0;
}
标签:
原文地址:http://www.cnblogs.com/clrs97/p/5027988.html