您的位置:首页 > 理论基础 > 计算机网络

codeforces 223E 计算几何 图论 网络流思想

2012-09-25 13:03 351 查看
http://codeforces.com/problemset/problem/223/E

题意: 给你一堆坐标点,然后告诉你他们之间的连接情况,所有的边都是双向的,并且图是连通的。边数,点数都是10w级别

然后开始询问,每个询问是输入图中某个多边形的所有顶点,然后问你这个多边形内部一共有几个点(包括边界上的点)

题解在这里http://codeforces.com/blog/entry/5301

看完后就懂了,关键就是利用流的思想,当选定某个简单多边形的时候,内部的点数就等于流进去的流量和减去流出来的流量和,反正就是流量差,怎么定义很自由

统计的时候不能暴力

利用坐标的极角序处理出一个前缀和就可以很快得到答案

具体见代码

关于多边形的内部究竟在哪一侧还是搞了我很长时间,太纠结了

#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define MP make_pair
#define PB push_back
const int maxn = 100010;
const double inf = 1e10;
struct Point {
double x,y;
Point(){};
Point(double sx,double sy) : x(sx),y(sy){}
}p[maxn];
double operator / (const Point &b,const Point &a) {
return atan2(b.y-a.y,b.x-a.x);
}
bool operator < (const Point &a,const Point &b){
if(a.x!=b.x)
return a.x<b.x;
return a.y<b.y;
}
inline double cross(double x1,double y1,double x2,double y2){
return x1*y2-x2*y1;
}
inline double chacha(Point s,Point a,Point b){
return cross(a.x-s.x,a.y-s.y,b.x-s.x,b.y-s.y);
}
struct Edge{
double ang;
int to;
Edge(){}
Edge(double a,int t):ang(a),to(t){};
bool operator < (const Edge &cmp) const{
return ang<cmp.ang;
}
};
vector<Edge> edge[maxn];

map<pair<int,int>,int> sum,flow;

int all[maxn];

int n,m;

inline void add_edge(int u,int v)
{
Edge k;
k.to=v;k.ang=p[v]/p[u];
edge[u].PB(k);
flow[MP(u,v)]=0;
}
bool vis[maxn];
int dfs(int u,int f)
{
vis[u]=true;
int cnt=1;
for(vector<Edge>::iterator it=edge[u].begin();it!=edge[u].end();it++)
{
int v=it->to;
if(!vis[v]) cnt+=dfs(v,u);
}
if(f)
{
flow[MP(f,u)]+=cnt;
flow[MP(u,f)]-=cnt;
}
return cnt;
}

int ss[maxn],tt[maxn];

vector<int> cut;
inline int gao(int a,int b,int c)
{
double bb = p[b]/p[a],cc = p[c]/p[a];
if(bb < cc)
{
return sum[MP(a,c)] - sum[MP(a,b)] - flow[MP(a,c)];
}
else
{
return all[a] + sum[MP(a,c)] - sum[MP(a,b)] - flow[MP(a,c)];
}
}
void solve()
{
int ans=0,num=cut.size(),i;
double s=0;p[0]=Point(0,0);
for(i=0;i<num;i++)
s+=chacha(p[0],p[cut[i==0 ? num-1 : i-1]],p[cut[i]]);
if(s>0) reverse(cut.begin(),cut.end());//变成顺时针
for(i=0;i<num;i++)
{
int tmp=gao( cut[i], cut[(i==0 ? num-1 : i-1)] , cut[(i+1)%num] ) ;
ans+=tmp;
}
printf("%d\n",ans+num);
}
int main()
{
int u,v,q,k,i,j,leftmost,T,cir,c;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++) scanf("%d%d",&ss[i],&tt[i]);
for(i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
for(i=1;i<=m;i++)
{
add_edge(ss[i],tt[i]);
add_edge(tt[i],ss[i]);
}
p[T=n+1]=Point(-inf,0);
for(leftmost=i=1;i<=n;i++)
if(p[i]<p[leftmost]) leftmost=i;
add_edge(T,leftmost);
add_edge(leftmost,T);
dfs(T,0);
for(i=1;i<=n+1;i++) sort(edge[i].begin(),edge[i].end());
for(i=1;i<=n+1;i++)
{
int pre=i;
sum[MP(i,i)] = 0;
for(vector<Edge>::iterator it=edge[i].begin();it!=edge[i].end();it++)
{
all[i]+=flow[MP(i,it->to)];
sum[MP(i,it->to)] = sum[MP(i,pre)] + flow[MP(i,it->to)];
pre=it->to;
}
}
scanf("%d",&q);
while(q--)
{
scanf("%d",&k);cut.clear();
for(i=1;i<=k;i++) scanf("%d",&c),cut.PB(c);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络 iterator struct c