题意:已知一个圆上顺时针放着 n 个点,这 n 个点中有m对顶点之间有连线,连线要么在园外要么在圆内,每个点最多连接一条边,问是否存在一种连接情况满足所有的
边都不相交。
分析:将每条边看成两个点 i ,i+m 分别表示边在内部和在外部,
如果两条边i,j的端点存在序号上的交叉,则这两对点之间的连线一个在外部一个在内部
即如果存在 i,则必存在 j+m ,如果存在 j ,则必存在 i+m,
如果存在 i+m,则必存在 j ,如果存在 j+m ,则必存在 i,
建图的时候连的边为
i -> j+m
j -> i+m
i+m -> j
j+m -> i
求出强连通分量并染色,判断是否存在冲突的情况即可。
#include#include #define maxn 1100#define clr(x)memset(x,0,sizeof(x))#define min(a,b)(a)<(b)?(a):(b)#define max(a,b)(a)>(b)?(a):(b)struct Edg{ int u,v;}e[1100];struct node{ int to,next;}edge[1000000];int tot;int head[maxn];void add(int s,int t){ edge[tot].to=t; edge[tot].next=head[s]; head[s]=tot++;}int dfn[maxn];int low[maxn];int sta[maxn];int ins[maxn];int col[maxn];int top,sn,ti;void tarjan(int u){ dfn[u]=low[u]=++ti; sta[++top]=u; ins[u]=1; int i,k; for(i=head[u];i;i=edge[i].next) { k=edge[i].to; if(dfn[k]==0) { tarjan(k); low[u]=min(low[u],low[k]); } else if(ins[k]) low[u]=min(low[u],dfn[k]); } if(dfn[u]==low[u]) { sn++; do { k=sta[top--]; ins[k]=0; col[k]=sn; }while(k!=u); }}int main(){ int n,m,i,j; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0;i e[i].v) { int tmp=e[i].u; e[i].u=e[i].v; e[i].v=tmp; } } tot=1; clr(head); for(i=0;i e[j].u&&e[i].v>e[j].v ||e[i].v>e[j].u&&e[i].v