第一行两个整数n和m,表示点与线段的数目。
接下来n行,每行两个整数x和y,表示第i个点的坐标,点从1到n编号。
接下来m行,每行四个整数p,q,V1和V2,表示存在一条从第p个点连向第q个点的线段,激活p->q这个方向的费用为V1,另一个方向费用为V2。
保证若两条线段相交,则交点是它们的公共端点。
输出一行一个正整数,表示最小总激活费用。
对于100%的数据,n≤3000,区域数不超过1000,点坐标绝对值不超过1W,每条边激活费用不超过100。
中国国家队清华集训 2012-2013 第二天 鸣谢lydrainbowcat
求PLCG
在对偶图上建图,求最小有向生成树。
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <cctype> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define pb push_back #define mp make_pair #define MAXN (4000+50) #define eps (1e-3) #define MAXE (3000*3000+10) typedef long long ll; namespace geometry { struct P { int x,y; P(double x=0,double y=0):x(x),y(y){} friend istream& operator >> (istream &_,P &p) { scanf("%d%d",&p.x,&p.y); return _; } }; typedef P V; V operator + (V A,V B) {return V(A.x+B.x,A.y+B.y);} V operator - (V A,V B) {return V(A.x-B.x,A.y-B.y);} double Arctan2(const P p){return atan2(p.y,p.x); } }; using namespace geometry; P points[MAXN]; struct node{ // define a edge which has a vector and a startpoint node *another; double alpha; int to,cost,belong; node(){} node(double _alpha,int _to,int _cost):another(NULL),alpha(_alpha),to(_to),cost(_cost){belong=0;} void print(){ cout<<to<<' '<<belong<<endl; } }; vector<node*> a[MAXN]; vector<node*>::iterator it; bool Compare(const node *a, const node *b) { return a->alpha < b->alpha; } void Add(int x,int y,int t1,int t2) { if (!t1) t1=INF; if (!t2) t2=INF; V v=points[y] - points[x]; node *node1=new node(Arctan2(v),y,t1); node *node2=new node(Arctan2(P(0,0)-v),x,t2); node1->another = node2; node2->another = node1; a[x].pb(node1); a[y].pb(node2); } void DFS(int x, node * from, int aim,int cnt){ from -> belong = cnt; if (x==aim) return; vector<node*>::iterator it = lower_bound( a[x].begin() , a[x].end() , from->another , Compare ); it++; if (it==a[x].end()) it=a[x].begin(); DFS( (**it).to , *it , aim , cnt ); } struct edge{ int u,v,w; edge(){} edge(int _u,int _v,int _w):u(_u),v(_v),w(_w){} }e[MAXE]; int tot=0; int id[MAXN],in[MAXN],pre[MAXN],vis[MAXN]; int MST_Directed(int root,int numv,int nume) { int ans=0; while (1) { For(i,numv) in[i]=INF,pre[i]=INF; For(i,nume) { int u=e[i].u,v=e[i].v,w=e[i].w; if (w<in[v]&&u!=v) { pre[v]=u; in[v]=w; } } For(i,numv) { if (i==root) continue; if (in[i]==INF) return -1; } in[root]=0; For(i,numv) ans+=in[i]; memset(id,-1,sizeof(id)); memset(vis,-1,sizeof(vis)); int cntnode=0; For(i,numv) { int v=i; while( vis[ v ] !=i && id[v] == -1 && (v!=root) ) { vis[v]=i; v=pre[v]; } if (v!=root && id[v] == -1 ) { ++cntnode; for(int u=pre[v];u!=v;u=pre[u]) id[u]=cntnode; id[v]= cntnode; } } if (!cntnode) break; For(i,numv) { if (id[i]==-1) { id[i]= ++ cntnode; } } For(i,nume) { int v=e[i].v; e[i].u=id[e[i].u]; e[i].v=id[e[i].v]; if (e[i].u != e[i].v ) { e[i].w-=in[v]; } } numv=cntnode; root=id[root]; } return ans; } int n,m; int main() { // freopen("bzoj2960.in","r",stdin); // freopen(".out","w",stdout); cin>>n>>m; For(i,n) scanf("%d%d",&points[i].x,&points[i].y); For(i,m) { int x,y,t1,t2; scanf("%d%d%d%d",&x,&y,&t1,&t2); Add(x,y,t1,t2); } For(i,n) sort(a[i].begin(),a[i].end(),Compare); int cnt=0; For(x,n) { for( it = a[x].begin() ; it!=a[x].end() ; it++ ) { if (!(**it).belong) { DFS((**it).to,*it,x,++cnt); } } } For(x,n) { vector<node*>::iterator it; for( it = a[x].begin() ; it!=a[x].end() ; it++ ) { if (INF!=(**it).cost) { e[++tot]=edge((*it)->another->belong,(*it)->belong,(**it).cost); } } } int ans=0; For(i,cnt) { e[++tot]=edge(cnt+1,i,0x1010101 ); } cout<<MST_Directed(cnt+1,cnt+1,tot) - 0x1010101 <<endl; return 0; }