题目描述:化学很神奇,以下是烷烃基。
假设如上图,这个烷烃基有6个原子和5个化学键,6个原子分别标号1~6,然后用一对数字 a,b 表示原子a和原子b间有一个化学键。这样通过5行a,b可以描述一个烷烃基
你的任务是甄别烷烃基的类别。
原子没有编号方法,比如
1 2
2 3
3 4
4 5
5 6
和
1 3
2 3
2 4
4 5
5 6
是同一种,本质上就是一条链,编号其实是没有关系的,可以在纸上画画就懂了
输入:
输入第一行为数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b)
数据保证,输入的烷烃基是以上5种之一
输出:
每组数据,输出一行,代表烷烃基的英文名
sample:
Input
2
1 2
2 3
3 4
4 5
5 6
1 4
2 3
3 4
4 5
5 6
Output
n-hexane
3-methylpentane
题目思路:
本题的思路就是找到这五种烷烃的规律,首先题目中说明了原子编号没有固定的方法,这样我们只能看原子与化学键之间的数量关系,那么观察可以看到,n-hexane所有的化学键只能连接两个原子,2,3-dimethylbutane有两个原子连接三个化学键,2,2-dimethylbutane有一个原子连接四个化学键,对于这三种烷烃比较容易求得,也就是用一个一维数组记录下来每个原子连接的化学键个数,分为没有3、有两个3、有一个4三种情况。
但是剩余两种他们都有一个原子连接三个化学键,这样我们发现,3-methylpentane中连接三个化学键的原子周围的原子有两个是连接两个化学键的,而2-methylpentane中连接三个化学键的原子周围的原子有一个是连接两个化学键的,所以我们可以用矩阵表示成无向图,记录下每一条边(输入的时候是一条边,编程的时候把对称的点对加进去),遍历每个点找到哪个点有三条边(主题题目里提到原子没有编号方法,所以每一个原子都有可能是,所以只能扫描一遍确认),找到这个点之后记录下三条边对应的三个点,再遍历这三个点,找找他们周围有几条边,分为两个点有两条边、一个点有两条边两种情况。
代码如下:
#include<iostream>
using namespace std;
int main()
{
int t;
int aa[3]={0,0,0};//记录一个有三条临边的点周围的三个点
cin>>t;
for(int i=1;i<=t;i++)
{
int count1=0;//记录下有三条临边的点的个数
int count2=0;//记录下有四条临边的点的个数
int s[7]={0,0,0,0,0,0,0};//记录下每个点有多少临边
int ss[7][7]=//把输入的边用无向图记录下来
{
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0}
};
int a,b;
for(int j=1;j<=5;j++)
{
cin>>a>>b;
s[a]++;//由于是无向图,那么两个点都应该算一次
s[b]++;
ss[a][b]++;//记录下边,同时由于无向图反过来再记录一次
ss[b][a]++;
}
for(int k=1;k<=6;k++)
{
if(s[k]==3)
count1++;
if(s[k]==4)
count2++;
}
if(count1==0&&count2==0)//没有点有三条和四条临边
{
cout<<"n-hexane"<<endl;
}
else if(count1==2)//有两个点有三条临边
{
cout<<"2,3-dimethylbutane"<<endl;
}
else if(count2==1)//有一个点有四条临边
{
cout<<"2,2-dimethylbutane"<<endl;
}
else
{
for(int j=1;j<=6;j++)
{
int count3=0;//记录下有三条临边的点的个数
for(int k=1;k<=6;k++)
{
if(ss[j][k]==1)//有这条边就加入到数组a中
{
aa[count3]=k;//如果这一遍循环数组a不满没关系,下一次由于count3清零,会重新覆盖掉数组a,直到数组a满足有三个点为止
count3++;
}
if(count3==3)//双重循环是不能直接break的,需要强制让内层外层都满足循环条件才能退出
{
j=6;
k=6;
}
}
}
int count5=0;//记录有三条临边的点周围的三个点有两条临边的个数
for(int k=0;k<=2;k++)
{
int count4=0;//记录相邻的点临边的个数
for(int j=1;j<=6;j++)
{
if(ss[j][aa[k]]==1)//有这条边那就成立
count4++;
}
if(count4==2)
count5++;
}
if(count5==2)//有三条临边的点周围的点有两条临边的个数为2
cout<<"3-methylpentane"<<endl;
if(count5==1)//有三条临边的点周围的点有两条临边的个数为1
cout<<"2-methylpentane"<<endl;
}
}
return 0;
}
运行结果:
来源:CSDN
作者:Carbonium14
链接:https://blog.csdn.net/carbonium14/article/details/104688583