平面几何

背景

...
里斯本的绿荫的街道上每天都有熙熙攘攘的人群...这座座落在半岛西岸的城市..每天都充满着安静的气息...
人们不必为了食物而整日的发愁...每个人都可以在这里...在一片属于自己的角落...分享着午后的温暖de阳光...
...

描述

这一天下午...在学校的课堂里..一些训练生在一起讨论一道困难的平面几何题...
可是因为这题的条件众多..想从纷繁复杂的条件里推出最后的结果...并不是一件容易的事情...
于是...如果可以根据现在的条件...把所有可以得到的结果都推出来...也许会很有帮助?

Task1: 统计平行线段总数...
Task2: 回答询问...

'Parallel.'(平行)..
'Vertical.' (垂直) ..还有
'No idea.' (不知道)

格式

输入格式

第一行依次是直线数n,条件数m...询问数...q..
紧接着是m个条件..p表示平行.v表示垂直.
直线用字母l加一个数字什么的..表示..

输出格式

Task1就不解释了...Task2会询问两条直线间的关系...
两条直线的关系会是下面三种情况之一..
`Parallel.' (平行)..
`Vertical.' (垂直) ..
`No idea.' (不知道)..

样例1

样例输入1

6 5 2
l1 p l2
l2 v l4
l2 p l3
l4 p l5
l4 v l6
l1 l3
l2 l6
Copy

样例输出1

7
Parallel.
Parallel.
Copy

样例2

样例输入2

2 2 0
l1 v l2
l1 p l2
Copy

样例输出2

There must be something wrong...
Copy

限制

出题人不透露

提示

告诉你们..最大的数据是n=200...
所有数据均可以在longint范围内得到解决.。

如果有矛盾的情形...那么在预处理阶段就应该结束...请参考Sample2...

输入的数据不要离散化...是按1到n的顺序顺序给出的..(...汗..)

不会询问 l1 和 l1 的关系...(...再说这个是重合...也不算平行...#)
不会询问不在输入里的直线....(..再说这个也啥用啊...)..

条件不会有重复的情况...例如(先告诉你l1和l2平行..又告诉你l1和l2平行....)
(但是会有先告诉你l1和l2平行..l2和l3平行...再告诉你..l1和l3平行...这个没关系..)

哎呀...测试数据都是很善意的...我们没有刻意要害大家...也没有刻意要卡时间的数据呀...

解题思路:

两种方法

1.和团伙相同,并查集,a[x]表示与x垂直的一组。

2.Floyd,比较简单。

方法1(Floyd)世杰法

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int n,m,q,w[202][202],ans=0;
 7 char l,c;
 8 int main()
 9 {
10     freopen("1697.txt","r",stdin);
11     memset(w,0x3f,sizeof(w));
12     scanf("%d%d%d",&n,&m,&q);
13     for(int i=1;i<=m;i++)
14     {
15         l=getchar();
16         int r1,r2;
17         l=getchar();
18         scanf("%d",&r1);
19         l=getchar();
20         scanf("%c",&c);
21         l=getchar();
22         l=getchar();
23         scanf("%d",&r2);
24         if(w[r1][r2]>10000)
25         {
26         if(c=='p')
27             w[r1][r2]=1;
28         if(c=='v')
29             w[r1][r2]=-1;
30         w[r2][r1]=w[r1][r2];
31         }
32         else
33         {
34             printf("There must be something wrong...");
35             return 0;
36         }
37     }
38     for(int k=1;k<=n;k++)
39         for(int i=1;i<=n;i++)
40             for(int j=1;j<=n;j++)
41                 if(w[i][j]>10000&&(w[i][k]*w[k][j]==1||w[i][k]*w[k][j]==-1))
42                     w[i][j]=w[i][k]*w[k][j];
43     for(int i=1;i<=n;i++)
44         for(int j=1;j<=n;j++)
45             if(w[i][j]==1&&i!=j)
46                 ans++;
47         printf("%d\n",ans/2);
48     for(int i=1;i<=q;i++)
49     {
50         int r3,r4;
51         l=getchar();
52         l=getchar();
53         scanf("%d",&r3);
54         l=getchar();
55         l=getchar();
56         scanf("%d",&r4);
57         if(w[r3][r4]==1)
58             printf("Parallel.\n");
59         if(w[r3][r4]==-1)
60             printf("Vertical.\n");
61         if(w[r3][r4]>10000)
62             printf("No idea.\n");
63     }
64     return 0;
65 }

方法2:(并查集法)自制:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 using namespace std;
  5 int find(int);
  6 void unionn(int,int);
  7 int C(int x);
  8 int father[202],u,v,w,x,y,n,m,q,a[202],cnt=0,pop=0,tot[202],qq[202][202];
  9 char litter1,litter2,litter3,litter4,con;
 10 int main()
 11 {
 12     //freopen("1697.txt","r",stdin);
 13     memset(qq,0,sizeof(qq));
 14     memset(a,0,sizeof(a));
 15     scanf("%d%d%d",&n,&m,&q);
 16     scanf("%c",&litter1);
 17     for(int i=1;i<=n;i++)
 18     father[i]=i;
 19     for(int i=1;i<=m;i++)
 20     {
 21     scanf("%c%d%c%c",&litter1,&x,&litter2,&con);
 22      if(con=='p')
 23      {
 24         scanf("%c%c%d%c",&litter1,&litter2,&y,&litter3);
 25         int r1=find(x);
 26         int r2=find(y);
 27           int r3=find(a[x]);
 28           if (r2==r3)
 29           {
 30         printf("There must be something wrong...");
 31         return 0;
 32         }
 33         unionn(r1,r2);
 34         
 35         qq[r1][r2]=1;
 36      }
 37      if(con=='v')
 38      {
 39         scanf("%c%c%d%c",&litter1,&litter2,&y,&litter3);
 40         int r1=find(y);
 41         int r2=find(x);
 42         if(r1==r2)
 43         {
 44         printf("There must be something wrong...");
 45         return 0;
 46         }
 47         if(a[x]==0) a[x]=r1;
 48         else
 49         {    int r3=find(a[x]);
 50              unionn(r1,r3);
 51              qq[r1][r3]=1;
 52          }
 53         if(a[y]==0)  a[y]=r2;
 54         else
 55         {
 56             int r4=find(a[y]);
 57             unionn(r2,r4);
 58             qq[r2][r4]=1;    
 59         }}}
 60     
 61     for(int i=1;i<=n;i++)
 62     {
 63         v=find(i);
 64         tot[v]++;
 65     }
 66     for(int j=1;j<=n;j++)
 67     if(tot[j]>1)
 68     pop+=C(tot[j]);
 69     printf("%d\n",pop);
 70     for(int i=1;i<=q;i++)
 71     {
 72     scanf("%c%d%c%c%d",&litter1,&x,&litter2,&litter3,&y);
 73     int r1=find(x);
 74     int r2=find(y);
 75     int r3=find(a[x]);
 76     if(r1==r2)
 77     {printf("Parallel.\n");
 78     continue;
 79 }
 80     if(r3==r2)
 81  {   printf("Vertical.\n");
 82   continue;
 83 }
 84     printf("No idea.\n");
 85     }
 86 }
 87     int find(int x)
 88 {
 89     if(father[x]!=x)
 90     father[x]=find(father[x]);
 91     return father[x];
 92 }
 93 void unionn(int r1,int r2)
 94 {
 95     father[r2]=r1;
 96 }
 97 int C(int x)
 98 {
 99     w= x*(x-1)/2;
100     return w;
101 }

补充:

转载于:https://www.cnblogs.com/gzy20020702/p/7412908.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值