今天的第一个题
如果我们有这样的一组数据
9 11
7 8
8 9
9 7
4 1
7 3
1 2
2 5
5 6
6 2
1 3
3 4
为了更好的对照,我们把相应的关系图也给画出来
差不多就是上面这样
从图来看我们是能够直接看出来,1-2和3-7
其他不满足条件的路基本都有一个共同特征,能够与其他的路连接成一个闭合的环
所以我们就可以通过排除所有闭合的环上的路线,剩余的路线就是最终的结果
为了满足题目要求的输出,我们肯定是要排序的。
1 2
1 3
1 4
2 5
2 6
3 4
3 7
5 6
7 8
7 9
8 9
假设我们从城市1开始走,走的方法就是深度优先算法
从1往下走1-2走到2
判断城市2是否是走过的城市,不是就继续往下走
从2往下走2-5走到5
判断城市5是否是走过的城市,不是,继续往下走
从5往下走5-6,走到6
判断城市6是否是走过的城市,不是,继续往下走
从6往下走6-2,走到2
判断城市2是否是走过的城市,是。说明前面形成了一个环,往前面找,找到起点为2的路线,并将沿途的所有路线都做标记
所以包括本身,以及沿途上的2-6,5-6,2-5都进行标记
所以从1-2以上的所有路线都遍历完了
然后从1-3的路线开始走
判断城市3,继续往下走-7
判断城市7,继续往下走-8
判断城市8,继续往下走-9
判断城市9,继续往下走-7
判断城市7,已经走过了,标记沿途的路线7-9,8-9,7-8
我们继续从城市3走,往下走-4
判断城市4,继续往下走-1
判断城市1,已经走过了,标记沿途的路线1-3,3-4,1-4
所有的路线都判断完毕,最终输出没有标记的路线
1-2和3-7
其中是需要好几个标记
一个标记走过的路线,
一个标记走过的城市
一个标记成环的路线
最终的代码如下
#include<iostream>
using namespace std;
struct Data
{
int a;
int b;
}data[5003];
int don[5003]={0};//标记走过的路线
int result[5003]={0};//记录最终结果
int steep[200];//记录已经走过的城市
int n,m;
int run(int start,int end)
{
int mid=(start+end)/2;
int a=start;
int b=mid+1;
Data shadow[5003];
int len=0;
while(a<=mid&&b<=end)
{
if(data[a].a<data[b].a)
{
shadow[len++]=data[a++];
}
else
if(data[a].a==data[b].a)
{
if(data[a].b<data[b].b)
shadow[len++]=data[a++];
else
shadow[len++]=data[b++];
}
else
shadow[len++]=data[b++];
}
while(a<=mid)
shadow[len++]=data[a++];
while(b<=end)
shadow[len++]=data[b++];
for(int i=0;i<len;i++)
data[start+i]=shadow[i];
}
int sorting(int start,int end)
{
if(start>=end)
return 0;
int mid=(start+end)/2;
sorting(start,mid);
sorting(mid+1,end);
run(start,end);
}
//标记沿途的路线
int clear(int present,int goal,int flag)
{
result[present]=1;
if(flag==0)
if(data[present].a==goal||data[present].b==goal)
return 0;
present=don[present];
clear(present,goal,0);
}
int finding(int present,int cit)
{
if(steep[cit])
{
clear(present,cit,1);
return 0;
}
for(int i=1;i<=m;i++)
{
if(don[i]==0)
{
if(data[i].a==cit)
{
don[i]=present;//标记走过的路线,记录上一步
steep[data[i].a]=1;//标记走过的城市
finding(i,data[i].b);//前往下一个城市
}
if(data[i].b==cit)
{
don[i]=present;//标记走过的路线,记录上一步
steep[data[i].b]=1;//标记走过的城市
finding(i,data[i].a);//前往下一个城市
}
}
}
}
int main()
{
cin>>n>>m;
int a,b;
for(int i=1;i<=m;i++)
{
cin>>a>>b;
//存入时a必须小于b
if(a>b)
data[i].a=b,data[i].b=a;
else
data[i].a=a,data[i].b=b;
}
sorting(1,m);//排序
finding(1,data[1].a);
for(int i=1;i<=m;i++)
{
if(result[i]==0)
cout<<data[i].a<<' '<<data[i].b<<endl;
}
}
总结下来这一个题就是并查集,深度优先算法的集合。
主要还是深度优先算法
根据探索出来的特殊条件执行特殊命令,得出最终的结果