UVA - 10129 Play on Words(欧拉路)

题目链接

题意:给出n个单词,问是否可以把所有单词都拍成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同(想象成语接龙)

分析:不难发现,除了起始单词和结束单词,每个单词均连接了两个单词(一进一出),而起始单词只有出,结束单词只有进,

把每个单词抽象为一个点,会发现这是有像图的欧拉路问题,当存在欧拉路时,存在解,有向图存在欧拉路的条件是,忽略边的方向原图连通,除起点和终点外,所有点的出入度都相等,起点 出度=入度+1,终点 出度+1=入度

代码中用并查集判断图的连通性,可以dfs写

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=1e5+200;
int in[30],ou[30],f[N],vis[N];
vector<int>e[30];
string s[N];
int getf(int x)
{
    return f[x]==x?x:f[x]=getf(f[x]);
}
void mix(int x,int y)
{
    int tx=getf(x),ty=getf(y);
    if(tx!=ty)
        f[tx]=ty;
}
int main()
{
    ios::sync_with_stdio(0);
    int t,n;
    cin>>t;
    while(t--)
    {
        mem(in,0);
        mem(ou,0);
        mem(vis,0);
        for(int i=0;i<26;i++)
            e[i].clear();
        cin>>n;

        for(int i=1; i<=n; i++)
        {
            f[i]=i;
            cin>>s[i];
            e[s[i][0]-'a'].push_back(i);
            int l=0,r=s[i].length()-1;
            in[s[i][l]-'a']++;
            ou[s[i][r]-'a']++;
        }
        for(int i=1;i<=n;i++)
        {
            int r=s[i][s[i].length()-1]-'a';
            for(int j=0;j<e[r].size();j++)
                mix(i,e[r][j]);
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(!vis[getf(i)])
            {
                vis[getf(i)]=1;
                ans++;
            }
        }
        int f1=0,f2=0;
        for(int i=0;i<26;i++)
        {
            if(in[i]!=ou[i])
            {
                if(in[i]==ou[i]+1&&!f2)
                    f2=1;
                else if(in[i]+1==ou[i]&&!f1)
                    f1=1;
                else
                {
                    f2=f1=-1;
                    break;
                }
            }
        }
        if(ans!=1)cout<<"The door cannot be opened."<<endl;//图不连通
        else
        {
            if(f1==1&&f2==1||f1==0&&f2==0)
            cout<<"Ordering is possible."<<endl;
            else
                cout<<"The door cannot be opened."<<endl;
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您讲解一下拉格朗日方程的推导过程,以一维情况为例。 假设一个质点在一维坐标系上运动,其位置用 $q$ 表示,时间用 $t$ 表示。该质点的运动可以用拉格朗日函数 $L(q, \dot{q}, t)$ 描述,其中 $\dot{q}=\frac{dq}{dt}$ 表示质点的速度。 为了推导欧拉-拉格朗日方程,我们首先需要定义一个重要的量,即作用量 $S$。作用量定义为 $$S = \int_{t_1}^{t_2} L(q, \dot{q}, t) dt$$ 其中 $t_1$ 和 $t_2$ 表示质点运动的起点和终点。作用量可以理解为一个积分,它是拉格朗日函数在时间 $t_1$ 到 $t_2$ 内的时间积分。 接下来,我们需要考虑如何对作用量进行变分。变分是一种数学操作,它类似于求导,但是是对函数进行微小的偏移,即对函数进行微小的扰动。对于一个作用量 $S$,其变分可以表示为 $$\delta S = S[q+\delta q] - S[q]$$ 其中 $\delta q$ 表示对 $q$ 进行微小的扰动。 现在我们来考虑如何对作用量进行变分。首先,我们将作用量中的积分拆开,得到 $$\delta S = \int_{t_1}^{t_2} \left( \frac{\partial L}{\partial q} \delta q + \frac{\partial L}{\partial \dot{q}} \delta \dot{q} \right) dt$$ 其中第一个式子中的 $\frac{\partial L}{\partial q}$ 表示对 $L$ 关于 $q$ 的偏导数,第二个式子中的 $\frac{\partial L}{\partial \dot{q}}$ 表示对 $L$ 关于 $\dot{q}$ 的偏导数。 现在我们需要将 $\delta \dot{q}$ 转化为 $\delta q$。由于 $\dot{q}=\frac{dq}{dt}$,我们可以得到 $$\delta \dot{q} = \frac{d}{dt} \delta q$$ 将上式代入到 $\delta S$ 中,得到 $$\delta S = \int_{t_1}^{t_2} \left( \frac{\partial L}{\partial q} \delta q + \frac{\partial L}{\partial \dot{q}} \frac{d}{dt} \delta q \right) dt$$ 接下来,我们需要对第二个式子进行分部积分,得到 $$\delta S = \int_{t_1}^{t_2} \left( \frac{\partial L}{\partial q} - \frac{d}{dt} \frac{\partial L}{\partial \dot{q}} \right) \delta q dt + \left[ \frac{\partial L}{\partial \dot{q}} \delta q \right]_{t_1}^{t_2}$$ 现在我们需要对第二个式子进行讨论。由于质点在运动时,其位置 $q$ 和速度 $\dot{q}$ 在起点和终点上都是确定的,因此 $\delta q$ 在 $t_1$ 和 $t_2$ 处的值都应该为 0。因此,第二个式子等于 0。 最终,我们得到了欧拉-拉格朗日方程: $$\frac{d}{dt} \frac{\partial L}{\partial \dot{q}} - \frac{\partial L}{\partial q} = 0$$ 这个方程描述了质点的运动。如果我们能够求出拉格朗日函数 $L$,那么欧拉-拉格朗日方程就可以帮助我们计算质点的运动。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值