程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> codeforces 223E 計算幾何 圖論 網絡流思想

codeforces 223E 計算幾何 圖論 網絡流思想

編輯:C++入門知識

題意: 給你一堆坐標點,然後告訴你他們之間的連接情況,所有的邊都是雙向的,並且圖是連通的。邊數,點數都是10w級別
然後開始詢問,每個詢問是輸入圖中某個多邊形的所有頂點,然後問你這個多邊形內部一共有幾個點(包括邊界上的點)
 看完後就懂了,關鍵就是利用流的思想,當選定某個簡單多邊形的時候,內部的點數就等於流進去的流量和減去流出來的流量和,反正就是流量差,怎麼定義很自由
統計的時候不能暴力
利用坐標的極角序處理出一個前綴和就可以很快得到答案
具體見代碼
關於多邊形的內部究竟在哪一側還是搞了我很長時間,太糾結了
[cpp]
#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; 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved