学了欧拉后翻到紫书的这一题
学欧拉 (https://www.jianshu.com/p/e7524d6ab6ca)
(https://www.cnblogs.com/zdblog/articles/3725858.html)
欧拉的理解
欧拉即一笔画
欧拉回路:所有端点的度都是偶数
欧拉路径:除了起和末其他端点的度都是偶数
判断是否是欧拉路径
1.用dfs看是否是连通1体的,
比如上面这个图我随手画的就是3个连通块。
2.用欧拉路径的知识去判断
欧拉回路:所有端点的度都是偶数
欧拉路径:除了起和末其他端点的度都是偶数
比如下面这张图它是一个联通快,但是无法实现一笔过,就是欧拉。所以得用这个知识去判断是否是欧拉。
ac代码如下
#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstring>
using namespace std;
int all[30];
int mp[28][28];
int vi[28];
void getword()
{ string word;
cin>>word;
int fi=word[0]-'a'+1;
int len=word.size();
int en=word[len-1]-'a'+1;
all[fi]++;
all[en]--;
mp[fi][en]++;
vi[fi]++;
}
void dfs(int a)
{
for(int i=1;i<=26;i++)
if(mp[a][i]){mp[a][i]--;vi[a]--;dfs(i);}
for(int i=1;i<=26;i++)
if(mp[i][a]){mp[i][a]--;vi[i]--;dfs(i);}
}
int main(void)
{int n,m;
//freopen("abc.txt","r",stdin);
//freopen("123.txt","w",stdout);
scanf("%d",&n);
while(n--)
{scanf("%d",&m);
bool fau=0;
memset(all,0,sizeof(all));
memset(mp,0,sizeof(mp));
for(int i=1;i<=26;i++)vi[i]=0;
for(int i=1;i<=m;i++)
{
getword();
}
int cnt=0;
for(int i=1;i<=26;i++)
while(vi[i]){cnt++;dfs(i);}
if(cnt!=1)fau=1;
int fro=0,to=0;
if(m!=1&&fau==0)
for(int i=1;i<=26;i++)
{
if(all[i]==0)continue;
if(all[i]==1){fro++;continue;}
if(all[i]==-1){to++;continue;}
fau=1;break;
}
if(fau==0)printf("Ordering is possible.\n");
else printf("The door cannot be opened.\n");
}
}
练习题目
uva 12118
题意:有n个节点,有k条边,问要添加多少条边,能实现最少的时间经过这k条边。
思路:
1.最少的时间经过,那就是能否一笔过,如果不能一笔过,就得加边,把它变成一笔过,即是欧拉路径。
2.欧拉路径是起点和终点的度是奇数,而其他的度则是偶数。对一个连通块统计它的奇数点,每个奇数点除了起点和终点就加一条边使它的度变为偶数,最终得到这个连通块的cnt个奇点,由于两点一条直线,cnt/2就是要把这个连通块变成欧拉路径要添加的边数。每个连通块如此处理,最后得到的大连通块就是一个欧拉路径了,而把每个小连通块连起来的时候还要加边。