七天使的通讯


n个天使排成一条直线,某些天使之间需要互相联系,他们之间的通讯可以通过黑白两种通道中的一种;所有通道
必须在直线同侧(另一侧是地面);为了保证通讯效率,同种颜色的所有通道之间不能相交。请计算能否建立这种
通讯方案。
Input
第一行一个数T,表示接下来有T个询问。
对于每个询问:第一行两个数n,m,分别表示有n个天使、需要建立通讯线路的天使有m对;
接下来有m行,每行两个数a、b,表示a、b两个天使需要通讯。
1<=n<=5000,1<=m<=1000,1<=T<=10,1<=a<=n,1<=b<=n
数据保证每对(a,b)不重复,且a不等于b
Output
对于每个询问,输出一行"sane"表示有可行方案、"non"表示无解。
Sample Input
1
7 5
1 3
2 7
3 4
7 4
6 5
Sample Output
sane
【提示】
当两条线路有一对相同的端点时,这两条线路不相交。
也就是说,对于线路(a,b)和线路(c,d)(a<b且c<d),当且仅当a<c<b<d或者c<a<d<b时这两条线路相交。​

Sol:

将每个通道设为一个节点,先暴力判断每两条通道如果是同种颜色会不会相交,如果会相交就在这两个节点之间连无向边,说明它们不能为同种颜色(必须在二分图两边)。然后对组成的无向图进行二分图判定(DFS染色),如果染色成功说明该图是一个二分图,即有解,否则无解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1005,maxk=1000005;
int n,m,ca,color[maxn],tot,now[maxn],prep[maxk],son[maxk],wi[maxn][2];
bool bo;
void add(int x,int y)
{
    tot++,prep[tot]=now[x],now[x]=tot,son[tot]=y;
}
void dfs(int x,int y)
{
    color[x]=y;
    for (int i=now[x],so=son[i];i;i=prep[i],so=son[i])
	{
        if (color[so]==-1)
		{
            dfs(so,1-y);
        }
		else 
		if (color[x]==color[so]) bo=0;
    }
}
int main(){
    scanf("%d",&ca);
    while (ca--)
	{
        scanf("%d%d",&n,&m); bo=1;
        tot=0,memset(now,0,sizeof(now));
        for (int i=1;i<=m;i++)
		{
            scanf("%d%d",&wi[i][0],&wi[i][1]);
            if (wi[i][0]>wi[i][1]) 
			swap(wi[i][0],wi[i][1]);
        }
        int a,b,c,d;
        for (int i=1;i<=m;i++)
		{
            for (int j=1;j<=m;j++)
			{
                a=wi[i][0],b=wi[i][1],c=wi[j][0],d=wi[j][1];
                if (a<c&&c<b&&b<d) 
				     add(i,j),add(j,i);
            }
        }
        memset(color,-1,sizeof(color));
        for (int i=1;i<=m;i++) if (color[i]==-1) dfs(i,1);
        if (bo==1) puts("sane");
        else puts("non");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/cutemush/p/12814410.html