列表

详情


NC20474. [ZJOI2008]RISK

描述

经过连续若干年的推广,Risk这个游戏已经风靡全国,成为大众喜闻乐见的重要娱乐方式。
Risk这个游戏可以理解为一种简易的策略游戏,游戏者的目的是占领所有的土地。由于游戏规则的规定,只要两个国家相邻,就认为两个国家有交战的可能性。
我们现在希望知道在当前的局面下,哪些国家之间有交战的可能性。
注意,我们认为只有当两个国家的国界线有公共边的时候才认为相邻,若两个国家的领土只有公共点,则认为两个国家不相邻。每一个国家的边界由一系列线段组成,保证这个边界是一个简单多边形,即严格不自交。
为了定位每个国家的位置,我们还给出每个国家最庞大的一支军队的位置,保证这个位置一定出现在某一个形内,而不是出现在某条边界上。

输入描述

输入文件的第一行中包括两个整数n,m。分别表示地图上的国家数和描述国家的边界的线段的数量。
1 ≤ n ≤ 600,1 ≤ m ≤ 4000。
接下来n行,每行用一对数描述了某个国家的主力军队的坐标。
接下来m行,每行有4个数x1,y1,x2,y2,(x1,y1)-(x2,y2)描述了一条国界线。所有点的坐标都是0-10000之间的整数。保证输入的所有线段至多只会在线段交点处相交。整张地图上有且仅有一块面积无限的空白区域不属于任何国家。每一条国界线两侧的区域或者隶属于两个不同的国家,或者分隔了一个国家与那块无穷大的空白区域。即保证一条国界线两侧的区域不同时属于同一个国家或是同时都是空白区域。所有封闭区域内部包含且仅包含一支主力军队,表示了该区域的归属。 

例如上图中第一行的数据是合法的。而第二行中的数据都是不合法的。左边的那幅图包含线段两侧都是空白区域;中间的图包含线段两侧区域同时属于同一个国家;右边的图中军队被布置在了国界线上,因此非法;此外若最右侧的图中若没有军队也是非法的。保证输入文件提供的数据都是合法的,你的程序不需要进行数据合法性的判定。

输出描述

包括n行,每行第一个数字x表示有x个国家可能与这个国家交战,接着在同一行中升序输出x个整数,表示可能与这个国家交战的国家的编号。
国家按输入中给出的顺序从1到n编号。注意数字间严格以一个空格隔开,并且不要在行末输出多余的空白字符。

示例1

输入:

4 12
3 2
11 8
12 17
1 19
0 0 10 0
10 0 20 0
20 0 20 10
20 10 20 20
20 20 10 20
10 20 0 20
0 20 0 10
0 10 0 0
10 0 10 10
0 10 10 10
20 10 10 10
10 20 10 10

输出:

2 2 4
2 1 3
2 2 4
2 1 3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 13ms, 内存消耗: 4992K, 提交时间: 2022-07-23 00:13:30

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    char ch=getchar();int i=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
    return i*f;
}
inline void W(int x){
    static int buf[50];
    if(!x){putchar('0');return;}
    if(x<0){putchar('-');x=-x;}
    while(x)buf[++buf[0]]=x%10,x/=10;
    while(buf[0])putchar(buf[buf[0]--]+'0');
}

const int Maxn=1e4+50;
const double PI=acos(-1.0);
const double eps=1e-9;
inline int sgn(double x){return (int)(x>eps)-(x<-eps);}
struct P{
    int x,y;
    P(){}
    P(int x,int y):x(x),y(y){}
    friend inline P operator -(const P &a,const P &b){return P(a.x-b.x,a.y-b.y);}
    friend inline int operator *(const P &a,const P &b){return a.x*b.y-a.y*b.x;}
    inline double slope(){return atan2(y,x);}
}p[Maxn];
struct E{
    int a,b;
    E(){}
    E(int a,int b):a(a),b(b){}
}e[Maxn];

int n,m,a[Maxn],tot,g[Maxn],v[Maxn],nt[Maxn],ec=1,bl[Maxn],bl_p[Maxn],Pcnt;
inline void add(int x,int y){nt[++ec]=g[x];g[x]=ec;v[ec]=y;}
map< int,int >S_p[Maxn<<1];
inline int getid(int x,int y){
    x+=10000;
    if(S_p[x].count(y))return S_p[x][y];
    else return (S_p[x].insert(make_pair(y,++tot)),p[tot]=P(x-10000,y),tot);
}
namespace Area{

int vis[Maxn];
struct cmp{
    inline bool operator ()(const pair<double,int> &a,const pair<double,int> &b){
        int t=sgn(a.first-b.first);
        return (t<0)||(t==0&&a.second<b.second);
    }
};
set< pair<double,int>,cmp >S_l[Maxn];
int st[Maxn],top;
inline int area(){
    int res=0;
    for(int i=1;i<=top;i++)res+=p[v[st[i]^1]]*p[v[st[i]]];
    return res;
}
inline int getsuf(int now){
    double ang=(p[v[now]]-p[v[now^1]]).slope();
    int t=v[now];
    set< pair<double,int> >::iterator suf=S_l[t].lower_bound(make_pair((ang<=0)?ang+PI:ang-PI,0));
    if(suf==S_l[t].begin())return (*--S_l[t].end()).second;
    return (*--suf).second;
}
inline void dfs(int x){
    vis[x]=1;st[++top]=x;
    int suf=getsuf(x);
    if(vis[suf]){
        int ar=area();
        int nowP=(ar>0?++Pcnt:0);
        for(int i=1;i<=top;i++)bl[st[i]]=nowP;          
        for(;top>=1;--top){
            int a=v[st[top]^1],b=v[st[top]];
            S_l[a].erase(S_l[a].lower_bound(make_pair((p[b]-p[a]).slope(),st[top])));
        }
    }else dfs(suf);
}
inline void getarea(){
    for(int i=1;i<=tot;i++){
        for(int j=g[i];j;j=nt[j])
        S_l[i].insert(make_pair((p[v[j]]-p[i]).slope(),j));
    }
    for(int i=2;i<=ec;i++)
        if(!vis[i])dfs(i);
}

}

namespace Scanline{

int vis[Maxn],tp,tcnt;
struct T{
    int a,b,u,id;
    T(){}
    T(int a,int b,int u):a(a),b(b),u(u){}
    friend inline bool operator <(const T &a,const T &b){
        if(a.a==b.a&&a.u!=b.u)return a.u>b.u;
        else if(a.a==b.a)return (p[a.b]-p[a.a])*(p[b.b]-p[a.a])<0;
        else if(p[a.a].x!=p[b.a].x)return p[a.a].x<p[b.a].x;
        else return p[a.a].y>p[b.a].y;
    }
}t[Maxn];
struct cmp{
    inline bool operator ()(const T &a,const T &b){
        if(a.a==a.b)return (p[b.b]-p[a.a])*(p[b.a]-p[a.a])<0;
        if(b.a==b.b)return (p[a.b]-p[b.a])*(p[a.a]-p[b.a])>0;
        int t1=(p[b.b]-p[a.a])*(p[b.a]-p[a.a]),t2=(p[b.b]-p[a.b])*(p[b.a]-p[a.b]);
        int t3=(p[a.b]-p[b.a])*(p[a.a]-p[b.a]),t4=(p[a.b]-p[b.b])*(p[a.a]-p[b.b]);
        return (t1<0&&t2<=0)||(t2<0&&t1<=0)||(t3>0&&t4>=0)||(t4>0&&t3>=0);
    }
};
set<T,cmp>S;
void dfs(int x){
    vis[x]=1;if(p[x].y>p[tp].y)tp=x;
    for(int j=g[x];j;j=nt[j])if(!vis[v[j]])dfs(v[j]);
}
inline void connect(){
    tcnt=0;S.clear();
    for(int i=1,j=tot;i<=j;i++)
        if(g[i]&&!vis[i]){
            dfs(tp=i);
            t[++tcnt]=T(tp,tp,1);
        }
    for(int i=1;i<=tot;i++)
        for(int j=g[i];j;j=nt[j])
            if(p[v[j]].x>p[i].x){
                t[++tcnt]=T(i,v[j],0);
                t[++tcnt]=T(v[j],i,2);
            }
    sort(t+1,t+tcnt+1);
    for(int i=1;i<=tcnt;i++){
        if(t[i].u==0)S.insert(t[i]);
        else if(t[i].u==2)S.erase(S.find(T(t[i].b,t[i].a,0)));
        else{
            set<T>::iterator it=S.lower_bound(t[i]);
            if(it==S.begin())continue;
            --it;add(it->a,t[i].a);add(t[i].a,it->a);
        }
    }
}
inline void getarea(){
    tcnt=0;S.clear();
    for(int i=1;i<=n;i++){
        t[++tcnt]=T(a[i],a[i],1);
    }
    for(int i=1;i<=tot;i++){
        for(int j=g[i];j;j=nt[j]){
            if(p[v[j]].x>p[i].x){
                t[++tcnt]=T(i,v[j],0);
                t[tcnt].id=j^1;
                t[++tcnt]=T(v[j],i,2);
            }
        }
    }
    sort(t+1,t+tcnt+1);
    for(int i=1;i<=tcnt;i++){
        if(t[i].u==0)S.insert(t[i]);
        else if(t[i].u==2)S.erase(S.find(T(t[i].b,t[i].a,0)));
        else{
            set<T>::iterator it=S.lower_bound(t[i]);
            --it;bl_p[t[i].a]=bl[(it)->id];
        }
    }
}
}
bool isadj[Maxn][Maxn];
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        int x=read(),y=read();
        a[i]=getid(x,y);
    }
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        e[i].a=getid(x,y);
        x=read(),y=read();
        e[i].b=getid(x,y);
        add(e[i].a,e[i].b);
        add(e[i].b,e[i].a);
    }
    Scanline::connect();
    Area::getarea();
    Scanline::getarea();
    for(int i=2;i<=ec;i++)
        if(bl[i]&&bl[i^1]){
            isadj[bl[i]][bl[i^1]]=1;
        } 
    for(int i=1;i<=n;i++){
        static int st[Maxn],top;
        top=0;
        for(int j=1;j<=n;j++)if(i!=j&&isadj[bl_p[a[i]]][bl_p[a[j]]])st[++top]=j;
        W(top);
        for(int j=1;j<=top;j++)putchar(' '),W(st[j]);
        if(i!=n)putchar('\n');
    }
}

上一题