21. 成语接龙

小张非常喜欢与朋友们玩成语接龙的游戏,但是作为“文化沙漠”的小张,成语的储备量有些不足。现在他的大脑中存储了m个成语,成语中的四个汉字都用一个1000000以内的正整数来表示。现在小张的同学为了考验他给出了他一个成语做开头和一个成语做结尾,如果小张能通过成语接龙的方式说到结尾的成语,他就能够成功完成游戏。他想知道最少能说几个成语能够成功完成游戏。

 

 解题思路:

正解bfs

其他方法:

我们可以不用考虑成语中间的两个数字,如果使用这个成语来进行接龙,我们就相当于从成语的第一个数字通过一条路走到了另一个数字,这样的话每一个成语就相当于一条从成语第一个数字到结尾数字的一条路,因此直接用最短路模型求最短路即可。

这里需要注意我们再求的时候要特判开头成语和结尾成语是否是一个,如果是,输出1,否则以第一个成语的结尾为起点,最后一个成语的开头为终点,计算最短路,再加上开头结尾的2.

代码:

#include <cstring>  
#include <iostream>  
#include <algorithm>  
#include <queue>  
#include <map>  
#include <vector>  
using namespace std;  
int n, m;  
const int N = 1000010;  
int h[N], w[N], e[N], ne[N], idx;  
int dist[N];  
bool st[N];  
int s[4],ed[4];  
void add(int a, int b, int c)  
{  
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;  
}  
  
int spfa()  
{  
    memset(dist, 0x3f, sizeof dist);  
    dist[s[3]] = 0;  
    st[s[3]] = true;  
    queue<int> q;  
    q.push(s[3]);  
    while (q.size())  
    {  
        int t = q.front();  
        st[t] = false;  
        q.pop();  
        for (int i = h[t]; i != -1; i = ne[i])  
        {  
            int j = e[i];  
            if (dist[j] > dist[t] + w[i])  
            {  
                dist[j] = dist[t] + w[i];  
                if (!st[j])  
                {  
                    st[j] = true;  
                    q.push(j);  
                }  
            }  
        }  
    }  
    return dist[ed[0]];  
}  
int main()  
{  
    memset(h, -1, sizeof h);  
    ios::sync_with_stdio(false);  
    cin.tie(0);  
    cout.tie(0);  
    int n;  
    cin>>n;  
    int x[4];  
    for(int i=1;i<=n;i++){  
        cin>>x[0]>>x[1]>>x[2]>>x[3];  
        add(x[0],x[3],1);  
    }  
    for(int j=0;j<=3;j++){  
        s[j]=0;  
        cin>>s[j];  
        //cout<<s[j]<<endl;  
    }  
    for(int j=0;j<=3;j++){  
        ed[j]=0;  
        cin>>ed[j];  
    }  
    bool ff=1;  
    for(int j=0;j<=3;j++){  
        //cout<<s[j]<<ed[j];  
        if(s[j]!=ed[j]){  
            ff=0;break;}  
    }  
    if(ff){  
        cout<<1<<endl;  
        return 0;  
    }  
    else{  
        spfa();  
    if(dist[ed[0]]<0x3f3f3f3f/2)cout<<dist[ed[0]]+2<<endl;  
    else cout<<-1<<endl;  
    }   
    return 0;  
}  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值