p1127——遍历欧拉通路

题目链接
(这个题目第一眼看过去感觉和图好像关系不大,以为是一个dfs,后来菜才明白这边是用了欧拉通路的判定用做dfs的剪枝,最后的点不会 TLE。

#include<bits/stdc++.h>
using namespace std;
const int NN=1005;
struct DATA//cin和cout用怕了 还是char字符串叭……虽然这个题目好像用string没关系的 这边储存这个字符串和这个字符串的长度
{
    char s[25];
    int len;
};
int n;//表示字符串的个数
vector<DATA>linki;//表示字符串集合的数组
vector<int>G[NN];//用vector存图
int t1[30];//表示一个字母在字符串头出现的次数
int t2[30];//表示一个字母在字符串尾巴出现的次数
bool vis[NN];
bool ans;
int Q[NN];//储存dfs结果
bool cmp(DATA aa,DATA bb)
{
    if(strcmp(aa.s,bb.s)>0)return 0;
    else return 1;
}
void dfs(int k,int cnt)
{
    //cout<<"!!dfs:"<<linki[k].s<<endl;
    Q[cnt]=k;
    //printf("Q[%d]:%d\n",cnt,k);
    vis[k]=1;
    if(cnt==n-1)//如果cnt到了n-1 说明字符串已经搜索到第n个了,也就是有满足的词链出现了,直接输出叭
    {
        ans=1;//表示有词链
        for(int i=0; i<cnt; i++)
            printf("%s.",linki[Q[i]].s);
        printf("%s\n",linki[Q[cnt]].s);
        return;
    }
    for(int i=0; i<G[k].size(); i++)//G【k】里面的兄弟姐妹们是可以跟在k字符串后面的
    {
        int v=G[k][i];
        if(vis[v]!=1)
        {
            dfs(v,cnt+1);
            if(ans==1)return;//既然已经搜索到了那么就不搜了(反正就搜一次
            vis[v]=0;
        }
    }
    vis[k]=0;
}
int main()
{
    scanf("%d",&n);
    for(int i=0; i<n; i++)
    {
        DATA pp;
        scanf("%s",pp.s);
        pp.len=strlen(pp.s);
        t1[pp.s[0]-'a']++;//头上的字母在头上里面的数组++
        t2[pp.s[pp.len-1]-'a']++;//尾巴上的字母在尾巴的数组里面++
        linki.push_back(pp);
    }
    sort(linki.begin(),linki.end(),cmp);
//    //for(int i=0;i<n;i++){
//        cout<<i<<" "<<linki[i].s<<" ";
//    }
//    cout<<endl;
    for(int i=0; i<n; i++)//构造图
    {
        for(int j=i+1; j<n; j++)
        {
            DATA p1=linki[i];
            DATA p2=linki[j];
            if(p1.s[p1.len-1]==p2.s[0])
                G[i].push_back(j);
            if(p2.s[p2.len-1]==p1.s[0])
                G[j].push_back(i);
        }
    }
    bool pig=0;
    for(int i=0; i<n; i++)
    {
        int L=linki[i].len;
        char tmp[30];
        strcpy(tmp,linki[i].s);
        if(t1[tmp[0]-'a']==t2[tmp[0]-'a']+1)//!!!这边是欧拉通路的关键剪枝 也就是如果一个字符串的头部 在所有字符串中(t1,t2数组里面 在头部出现的次数比在尾巴上出现的次数多一,那么它就是我要的第一个字符串 也就是出度比入度多1(好像是这样叭)
        {
            pig=1;
            dfs(i,0);
            break;
        }
    }
    if(pig==0)dfs(0,0);//如果是欧拉回路,则任意一个字符串都行,既然要字典序最小那么就是第一个开始搜索
    if(ans==0)printf("***");
    return 0;
}

这个题目感觉……词链的字典序有点迷惑,一开始觉得对字符串的排序不应该用字典序(也就是上方的cmp)纠结了好久
因为
在这里插入图片描述
对于这个数据来说,aac.ca.c明显比这个我这个代码输出的字典序小w……总之代码是ac了,但是数据到现在都还是有点迷惑叭

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值