JZOJ 3846. 七天使的通讯(angelus)

题目

Description

n个天使排成一条直线,某些天使之间需要互相联系,他们之间的通讯可以通过黑白两种通道中的一种;所有通道必须在直线同侧(另一侧是地面);为了保证通讯效率,同种颜色的所有通道之间不能相交。请计算能否建立这种通讯方案。
 

Input

第一行一个数T,表示接下来有T个询问。
对于每个询问:第一行两个数n,m,分别表示有n个天使、需要建立通讯线路的天使有m对;接下来有m行,每行两个数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
 

Data Constraint

对于 20%的数据,1<=n<=50,1<=m<=15
对于 50%的数据,1<=n<=1000,1<=m<=300
对于 100%的数据,1<=n<=5000,1<=m<=1000,1<=T<=10,1<=a<=n,1<=b<=n
数据保证每对(a,b)不重复,且a不等于b
 

Hint

【提示】
当两条线路有一对相同的端点时,这两条线路不相交。
也就是说,对于线路(a,b)和线路(c,d)(a<b且c<d),当且仅当a<c<b<d或者c<a<d<b时这两条线路相交。

分析

 

  • 首先我们暴力找出两条线是否相交
  • 然后对边进行编号
  • 相交两边连边
  • 然后跑dfs 0,1染色即可

 

代码

 1 #include<cstdio> 
 2 #include<iostream> 
 3 #include<algorithm> 
 4 #include<cmath> 
 5 #include<cstring> 
 6 #include<string> 
 7 using namespace std;  
 8 int T,n,m,color[1007]; 
 9 int cnt,head[1007],next[2000007],rea[2000007]; 
10 struct sb 
11 { 
12     int l,r; 
13 }a[1007]; 
14   
15 bool check(int i,int j) 
16 { 
17     if (a[i].r<=a[j].l||a[j].r<=a[i].l) return 0; 
18     if (a[i].l<=a[j].l&&a[i].r>=a[j].r) return 0; 
19     if (a[i].r<=a[j].r&&a[i].l>=a[j].l) return 0; 
20     return 1; 
21 } 
22 struct A
23 {
24     int to,nx;
25 }g[100001];
26 int list[10001];
27 void add(int u,int v) 
28 { 
29     g[++cnt].to=v; g[cnt].nx=list[u]; list[u]=cnt;
30 } 
31 
32 void dfs(int u) 
33 { 
34     for (int i=list[u];i;i=g[i].nx) 
35     { 
36         int v=g[i].to; 
37         if (color[v]==-1) 
38         { 
39             color[v]=color[u]^1; 
40             dfs(v); 
41         } 
42     } 
43 } 
44 int main() 
45 { 
46     scanf("%d",&T); 
47     while (T--) 
48     { 
49         cnt=0; 
50         memset(list,0,sizeof(list)); 
51         memset(color,-1,sizeof(color)); 
52         scanf("%d%d",&n,&m); 
53         for (int i=1;i<=m;i++) 
54         { 
55             scanf("%d%d",&a[i].l,&a[i].r); 
56             if (a[i].l>a[i].r) swap(a[i].l,a[i].r); 
57             for (int j=1;j<i;j++) 
58                 if (check(i,j)) 
59                 { 
60                     add(i,j); 
61                     add(j,i); 
62                 } 
63         } 
64         for (int i=1;i<=m;i++) 
65             if (color[i]==-1) 
66             { 
67                 color[i]=0; 
68                 dfs(i); 
69             }
70         int flag=0; 
71         for (int i=1;i<=m;i++) 
72         { 
73             for (int j=list[i];j;j=g[j].nx) 
74             { 
75                 int u=i,v=g[j].to; 
76                 if (color[u]==color[v]) 
77                 { 
78                     flag=1; 
79                     break; 
80                 }    
81             } 
82             if (flag==1) break; 
83         } 
84         if (flag==1) printf("non\n"); 
85         else printf("sane\n"); 
86     } 
87 }

 

posted @ 2019-11-08 16:06  Melted_czj  阅读(189)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色