欧拉路(P1341 无序字母对)

欧拉路:就是一个连通图能够“一笔画完”
欧拉回路:画完之后能够回到起点

判断是不是欧拉回路的条件

1、首先必须是一个连通图,连通图就是连成图包含每一个点
2、
(1)无向连通图:每一个点都有偶数条边时,欧拉回路
有两个奇数条边的点 ,欧拉路
其他的不能构成欧拉路
(2)有向连通图:把每一个点入度(指向节点)记为-1,出度(指出节点)记为1,所有点入度出度相加为度,所有节点度为0,则为欧拉回路。
如果有两个节点不是0,并且一个是1,一个是-1,则为欧拉路,度为1的为起点,度为-1的为终点。

P1341 无序字母对

其实主要是写一写这个题的题解的

链接:
https://www.luogu.com.cn/problem/P1341

题意:

给你n个字符对,表示这两个字符对相邻,如果能够找到一个长度为n+1的字符串,使得能够满足上述的n个相邻的条件,满足输出字符串,反之,输出“No Solution”

这个题其实就是熟悉这个代码的。所以就没有思路了,直接上代码吧。

用并查集来判断是否能够形成连通图
如果 f[x]==x 满足条件的只有一个则就能形成连通图

int fin(int x)
{
    if(f[x]==x)return x;
    return f[x]=fin(f[x]);
}
。。。。。~~~~
int fx=fin(x),fy=fin(y);
if(fx!=fy)
f[fx]=fy;

输出图,用邻接矩阵将g[][]存图,在这里面判断是不是连通图可以减少一个循环

 string s;
  for(int i=1;i<=n;i++)
    {   cin>>s;
        g[s[0]][s[1]] ++;
        g[s[1]][s[0]] ++;
        gg[s[0]]++;
        gg[s[1]]++;
        int fx=fin(s[0]),fy=fin(s[1]);
        if(fx!=fy)
            f[fx]=fy;
        }

输出一个欧拉回路

void find(int j)
{

    for(int i=64;i<=125;i++)
        if(g[i][j]>0)
    {g[i][j]--;
     g[j][i]--;
     find(i);}
    arr[++aaa]=j;return ;
}

代码奉上:

#include<bits/stdc++.h>
using namespace std;
string word[30];
string ss;
inline int read()
{
	int num=0,f=1;char ch=getchar();
	while(!isalnum(ch))
	{if(ch=='-')f=-1;ch=getchar();}
	while(isalnum(ch))
	{num=num*10+(ch-'0');ch=getchar();}
	return num*f;
}
int f[159];
int fin(int x)
{
    if(f[x]==x)return x;
    return f[x]=fin(f[x]);
}
int gg[150] , g[150][150],arr[15000];
int aaa=0;
void find(int j)
{
    for(int i=64;i<=125;i++)
        if(g[i][j]>0)
    {g[i][j]--; g[j][i]--;
        find(i); }
    arr[++aaa]=j;return ;
}
int main()
{
    ios::sync_with_stdio(false);
   int n,m;
  cin>>n;
  for(int i=1;i<=150;i++)
    f[i]=i;
  string s;
  for(int i=1;i<=n;i++)
    {   cin>>s;
        g[s[0]][s[1]] ++;
        g[s[1]][s[0]] ++;
        gg[s[0]]++;gg[s[1]]++;
        int fx=fin(s[0]),fy=fin(s[1]);
        if(fx!=fy)
            f[fx]=fy;
        }
        int c=0,h=0;int ccc=0;
  for(int i=64;i<=150;i++)
    if(f[i]==i&&gg[i])
    ccc++;
   // cout<<ccc;
    for(int i=64;i<=150;i++)
        if(gg[i]%2!=0)
          {c++;if(!h)h=i;}
    if(!h)
    for(int i=64;i<=150;i++)
    if(gg[i]){h=i;break;}
    if(c&&c!=2){cout<<"No Solution";return 0;}
  if(ccc!=1){cout<<"No Solution";return 0;}
    find(h);
   // cout<<aaa<<endl;
    for(int i=aaa;i>=1;i--)
        cout<<char(arr[i]);
    cout<<endl;
}

其实原来还是不是很理解的,但是做完题就明白了很多,感觉这种图的还是有规律可循的,他们没有dp这么慢想,只要不和其他的算法结合的话还是不是很难的。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨晓翔同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值