做了两天,一直在用bfs来做dfs的题,于是就一直TLE到死。以为邻接矩阵不够快,改用邻接表,但是还是TLE。直到怀疑服务器挂有问题= =,上网找别人的代码交。第一个找到的交上去还是错的,直到找到这个参考代码出处。
于是就仿照写一两次,终于发现了几处写错的地方。(其实是发现bfs和dfs的区别)
是什么:把每个珠子看出一条边,珠子的两种颜色看成点。就是给出所有的边(无向)看看能不能找到欧拉回路(就是一笔画,起点和终点同是一个点)(而起点和终点不在一个点上的一笔画就是欧拉道路)
为什么:图的转换,把某些关系转化成边,点。解除是否存在什么什么的路径(方法),什么什么的最短路径(最优方法)。
怎么样:要知道存在欧拉回路的图,不管从哪一个点出发,都能顺利完成“一笔画”(证明:既然能够一笔画完整个图而回到起点,那可以把图看成一个圆,那在圆上选任意一点都能完成一笔画)。所以判断是不是欧拉回路接下来输出路径就简单了(可对于我来说,并不是T_T)。
而判断无向图是否为的欧拉回路有两个方面:
1,图是否联通的。
2,每个点的是否有偶数条边相连。
第 1 点直接用并查集做。
第 2 点在加入边时直接计算就是了。
以下是代码:
这是邻接矩阵的
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int fa[60];
int data[60][60];
int findfa(int i){
if(fa[i]==i) return fa[i];
fa[i]=findfa(fa[i]);
return fa[i];
}
void eur(int k){
for(int i=1;i<60;++i){
if(data[k][i]){
--data[k][i];
--data[i][k];
printf("%d %d\n",k,i);
eur(i);
//break;//这个不能加!
}
}
}
int main(){
int cas;
scanf("%d",&cas);
for(int casi=1;casi<=cas;++casi){
for(int i=0;i<60;++i)
fa[i]=i;
memset(data,0,sizeof(data));
int n;
scanf("%d",&n);
int a,b;
for(int i=0;i<n;++i){
scanf("%d%d",&a,&b);
int tmp=min(a,b);
b=a+b-tmp;
a=tmp;
++data[a][b];
++data[a][0]; //<span style="font-family: 'Microsoft YaHei';">计算和点连接的边的数量</span>
++data[b][a];
++data[b][0]; //也是<span style="font-family: 'Microsoft YaHei';">计算和点连接的边的数量</span>
if(findfa(a)!=findfa(b))
fa[findfa(b)]=findfa(a);
}
int flag=0,sta;
for(int i=1;i<60;++i){
if(data[i][0]%2) flag=1;
if(data[i][0]) sta=i;
}
for(int i=1;i<60;++i)
if(data[i][0]&&findfa(i)!=findfa(sta)) flag=1;
printf("Case #%d\n",casi);
if(flag){
printf("some beads may be lost\n");
if(casi!=cas) printf("\n");
continue;
}
eur(sta);
if(casi!=cas) printf("\n");
}
return 0;
}
而这是邻接表写的
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
int start,index;
int tot;
int upp;
int fa;
node(int i=0,int inndex=0){
index=i;
start=-1;
upp=-1;
tot=0;
fa=inndex;
}
};
node nda[110];
struct edge{
int next;
int sta,end;
int up;
int use;
edge(int a=0,int b=0,int c=0){
sta=a;
end=b;
use=0;
next=nda[a].start;
nda[a].start=c;
}
};
edge eda[16000];
int find(int a){
if(nda[a].fa==a) return a;
nda[a].fa=find(nda[a].fa);
return nda[a].fa;
}
void gotofind(int stain){
for(int x=nda[stain].start;x!=-1;x=eda[x].next){
if(eda[x].use==0){
eda[x].use=1;
eda[x^1].use=1;
stain=eda[x].end;
//cout<<eda[x].sta<<' '<<eda[x].end<<endl;
/*
<span style="white-space:pre"> </span>这个不能卸载递归前面,因为当递归结束回到这里输出的答案和题目要求不一样
<span style="white-space:pre"> </span>可是又觉这样说不过去,不符合欧拉回路的性质啊。。。好纠结,知道的留个言~谢谢啦!
<span style="white-space:pre"> </span> */
gotofind(stain);
cout<<eda[x].end<<' '<<eda[x].sta<<endl;
}
}
}
int main(){
int cas;
cin>>cas;
for(int casi=1;casi<=cas;++casi){
for(int i=0;i<55;++i){
node ini(0,i);
nda[i]=ini;
}
int n;
scanf("%d",&n);
int maxin=-1;
int ai,bi;
int k=0,sum=0;
for(int i=1;i<=n;++i){
scanf("%d%d",&ai,&bi);
edge tmp(ai,bi,k);
eda[k]=tmp;
++k;
edge tmp1(bi,ai,k);
eda[k]=tmp1;
++k;
++nda[ai].tot;
++nda[bi].tot;
maxin=max(maxin,ai);
maxin=max(maxin,bi);
int t1=find(nda[ai].fa),t2=find(nda[bi].fa);
if(t1!=t2)
nda[t1].fa=t2;
++sum;
}
int flag=0,stain=0,maxto=-1;
for(int i=1;i<=maxin;++i){
if(maxto<nda[i].tot){
maxto=nda[i].tot;
stain=i;
}
if(nda[i].tot%2)
flag=1;
}
int tfa=find(stain);
for(int i=0;i<=55;++i){
if(nda[i].tot&&tfa!=find(i)) flag=1;
}
cout<<"Case #"<<casi<<endl;
if(flag){
cout<<"some beads may be lost"<<endl;
if(casi!=cas) cout<<endl;
continue;
}
gotofind(stain);
if(casi!=cas) cout<<endl;
}
return 0;
}
关于dfs和bfs的应用区别(我的理解)是:
bfs:用于找最优
dfs:用于找有无
但是算法杀死很灵活的,并不是固定不变的。需要看情(xin)况(qing)使用