可以先A掉一道弱化版本的题目 , UVa1334
我帮助Udebug重置了上面这个题数据 , 这个题目所需要考虑的可能类型非常少 , 只要你的算法没有错误 , 几乎是难以出错的。
提示:
1. 本题可以考虑卷包裹算法(aka PSLG)
2. 这是个训练指南上的中级习题 , 想作预备学习的小伙伴可以先看看训练指南中的计算几何部分。
说几个细节:
调了很久 , 代码慎看
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <set>
#include <map>
#include <string>
#include <cassert>
using namespace std;
double eps = 1e-10;
int dcmp(double a) { return fabs(a)<eps?0:(a<0?-1:1); }
struct points
{
double x , y;
void read() { scanf("%lf%lf",&x,&y); }
points(double x = 0 , double y = 0):x(x),y(y){}
bool operator <(const points& b)const { return dcmp(x - b.x)==-1 || (dcmp(x - b.x)==0 && dcmp(y - b.y)==-1); }
bool operator ==(const points& b)const { return dcmp(x - b.x)==0 && dcmp(y - b.y)==0; }
};
struct edge
{
int b;
int used , num;
edge(int b = 0 , int used = 0 , int num = 0):b(b) , used(used) , num(num) {}
};
typedef points Vector;
typedef vector<points> polygon;
Vector operator +(Vector a , Vector b) { return Vector(a.x+b.x , a.y+b.y); }
Vector operator -(Vector a , Vector b ) { return Vector(a.x-b.x , a.y-b.y); }
Vector operator *(Vector a , double b) { return Vector(a.x*b , a.y*b ); }
Vector operator /(Vector a , double b) { return Vector(a.x/b , a.y/b ); }
double Dot(Vector a , Vector b) { return a.x*b.x+a.y*b.y; }
double Cross(Vector a , Vector b) { return a.x*b.y - b.x*a.y; }
double Length(Vector a) { return sqrt(Dot(a ,a )); }
double angle(Vector a , Vector b) { return acos(Dot(a , b)/Length(a)/Length(b)); }
double compareAngle( Vector a , Vector b ) { double res = angle(a , b); if(dcmp(Cross(a , b))<=0) res = -res; return res; }
bool onSegmenStrict(points p , points a , points b) { return dcmp(Cross(p-a , p-b))==0 && dcmp(Dot(p-a , p-b))==-1; }
int n , m;
const int maxn = 610;
const int maxm = 4100;
points cap[maxn];
int cnt;
map<points , int> dic;
points redic[maxm*2] ;
int tell(points a)
{
if(dic.count(a)) return dic[a];
redic[cnt] = a;
return dic[a] = cnt++;
}
vector<edge> g[maxm*2];
vector<int> abj[maxm*2];
vector<int> nabj[maxm*2];
set<int> con[maxm*2];
int whoIsWho[maxm*2];
int rewhoisw[maxm*2];
vector<polygon> ps;
vector<vector<int> > mark;
int book[maxm*2];
edge e[maxm*2];
double s[maxm*2];
int st[maxm*2];
int inPolygon(points p , polygon& poly)
{
int n = poly.size();
int wn = 0;
for(int i=0;i<n;i++)
{
int j = (i+1)%n;
if(onSegmenStrict(p , poly[i] , poly[j]) || p == poly[i] || p== poly[j]) return 0;
int k = dcmp(Cross(poly[j]-poly[i] , p - poly[i]));
int d1 = dcmp(poly[i].y - p.y);
int d2 = dcmp(poly[j].y - p.y);
if(k>0 && d1<=0 && d2>0) wn++;
if(k<0 && d2<=0 && d1>0) wn--;
}
return wn?-1:1;
}
double polygonArea(polygon& p)
{
int n = p.size();
double res = 0;
for(int i=1;i<n-1;i++) res+= Cross(p[i] - p[0] , p[i+1] - p[0]);
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("risk6.in","r",stdin);
#endif
while(scanf("%d%d",&n,&m)==2 && n+m)
{
cnt = 0;
ps.clear();
dic.clear();
for(int i=0;i<n;i++) { cap[i].read(); }
for(int i=0;i<m*2;i++) { g[i].clear() ; book[i] = 0; abj[i].clear(); con[i].clear(); }
for(int i=0;i<m;i++)
{
points a , b;
a.read();
b.read();
e[i*2] = edge(tell(b) , 0 , i*2);
e[i*2+1] = edge(tell(a) , 0 , i*2+1);
st[i*2] = tell(a);
st[i*2+1] = tell(b);
g[tell(a)].push_back(edge(tell(b) , 0 , i*2));
g[tell(b)].push_back(edge(tell(a) , 0 , i*2+1));
assert(tell(a) != tell(b));
}
//for(int i=0;i<cnt;i++) cout<<redic[i].x<<" "<<redic[i].y<<endl; cout<<endl<<endl;
for(int i=0;i<2*m;i++) if(!book[i])
{
int now = e[i].b;
Vector v = redic[e[i].b] - redic[st[i]];
polygon ne;
vector<int> nee;
while(true)
{
ne.push_back(redic[now]);
// if(now==0)
// cout<<"stay";
int who = -1;
//bool havesome = false;
Vector Best;
double bestAngle;
for(int j=0;j<g[now].size();j++) if(!g[now][j].used)
{
//havesome = true;
Vector here = redic[g[now][j].b] - redic[now];
if(v+here == Vector(0,0)) continue;
if(who == -1 || dcmp(compareAngle(v , here) - bestAngle)==1)
{
bestAngle = compareAngle(v , here);
//cout<<compareAngle(v , here)<<endl;
Best = here;
who = j;
}
}
// if(havesome==false) cout<<now<<endl;
//assert(havesome);
if(who==-1) continue;
g[now][who].used = 1;
book[g[now][who].num] = 1;
abj[g[now][who].num/2].push_back(ps.size());
nee.push_back(g[now][who].num/2);
if(now == st[i] && g[now][who].b == e[i].b) break;
//cout<<now<<" "<<g[now][who].b<<endl;
//cout<<redic[now].x<<" "<<redic[now].y<<" "<<" "<<redic[g[now][who].b].x<<" "<<redic[g[now][who].b].y<<endl;
v = redic[g[now][who].b] - redic[now];
now = g[now][who].b;
}
ps.push_back(ne);
mark.push_back(nee);
}
//for(int i=0;i<m;i++){ cout<<i<<" "; for(int j=0;j<abj[i].size();j++) cout<<abj[i][j]<<(j==abj[i].size()-1?"\n":" ");cout<<endl<<endl; }
set<int> forbid;
for(int i=0;i<ps.size();i++) if(dcmp(s[i] = polygonArea(ps[i]))<=0) forbid.insert(i);
//cout<<forbid.size()<<endl;
// cout<<ps.size()<<endl;
// for(int i=0;i<ps.size();i++) for(int j=0;j<ps[i].size();j++) cout<<tell(ps[i][j])<<(j==ps[i].size()-1?"\n":" ");
// cout<<endl<<endl;
memset(rewhoisw , -1 , sizeof(rewhoisw));
for(int i=0;i<n;i++)
{
int wh = -1;
double ar = 1e20;
for(int j=0;j<ps.size();j++) if(forbid.count(j)==0 && inPolygon(cap[i] , ps[j])<=0) if(dcmp(ar - s[j])>0) ar = s[j] , wh = j;
assert(wh!=-1);
whoIsWho[i] = wh;
rewhoisw[wh] = i;
}
//for(int i=0;i<n;i++) cout<<whoIsWho[i]<<" "; cout<<endl<<endl;
for(int i=0;i<m;i++) for(int j=0;j<abj[i].size();j++) if(rewhoisw[abj[i][j]]!=-1) nabj[i].push_back(abj[i][j]);
for(int i=0;i<m;i++) abj[i] = nabj[i];
for(int i=0;i<m;i++) if(abj[i].size()==2)
con[abj[i][0]].insert(abj[i][1]) , con[abj[i][1]].insert(abj[i][0]);
for(int i=0;i<ps.size();i++) if(rewhoisw[i]!=-1)
{
bool ok = false;
for(int j=0;j<mark[i].size();j++) if(abj[mark[i][j]].size()<2) { ok = true; break; }
if(!ok) continue;
int wh = -1;
double ar = 1e20;
for(int j=0;j<ps.size();j++) if(i!=j && rewhoisw[j]!=-1)
{
bool ok = true;
for(int k=0;k<ps[i].size();k++) if(inPolygon(ps[i][k] , ps[j])>=0) { ok = false; break; }
if(!ok) continue;
if(dcmp(ar - s[j])==1) ar = s[j] , wh = j;
}
if(wh!=-1) con[i].insert(wh) , con[wh].insert(i);
}
for(int i=0;i<n;i++)
{
cout<<con[whoIsWho[i]].size();
vector<int> resnow;
for(set<int>::iterator j=con[whoIsWho[i]].begin();j!=con[whoIsWho[i]].end();++j)
resnow.push_back(rewhoisw[*j]+1);
sort(resnow.begin() , resnow.end());
for(int j=0;j<resnow.size();j++) printf(" %d",resnow[j]);
printf("\n");
}
}
return 0;
}