图论-欧拉回路

欧拉回路:通过图中每条边恰好一次的回路

1:判别图中是否有欧拉回路

 

 

 

首先,如果一个图是欧拉图,则必须联通 

检查图是否联通:

使用并查集:

有且只有一个点满足:

par[i]==i

 

对于无向图,记录度数d

对于有向图,记录入度,出度

u->v

出度:以u为起点

入度:以v为终点

d_out[u]++,d_in[v]++;

欧拉回路 - HDU 1878 - Virtual Judge (vjudge.net)

#include<bits/stdc++.h>
const int maxn=1e3+1e1;
int n,m;
struct Dsu
{
    std::array<int,maxn>par;
    explicit Dsu()
    {
        for(int i=0;i<maxn;i++)par[i]=i;
    }
    int find(int x)
    {
        if(par[x]==x)return x;
        else return par[x]=find(par[x]);
    }
    void unite(int x,int y)
    {
        x=find(x);y=find(y);
        if(x!=y)par[y]=x;
    }
    bool same(int x,int y){return find(x)==find(y);}
};
std::array<int,maxn>degree;
void solve()
{
    Dsu dsu;
    int u,v;
    std::memset(&degree,0,sizeof(degree));
    for(int i=0;i<m;i++)
    {
        std::cin>>u>>v;
        degree[u]++;degree[v]++;
        dsu.unite(u,v);
    }
    int cnt=0;
    bool flag=true;
    for(int i=1;i<=n&&flag;i++)
    {
        if(degree[i]&1)flag=false;
        if(dsu.par[i]==i)cnt++;
        if(cnt>=2){flag=false;}
    }
    if(!flag)
    {
        std::cout<<"0\n";
        return;
    }
    else std::cout<<"1\n";
}
int main()
{
    while(std::cin>>n>>m&&n)
    {
        solve();
    }
    return 0;
}

 

 

 

 Ant Trip - HDU 3018 - Virtual Judge (vjudge.net)

#include<bits/stdc++.h>
const int maxn=1e5+1e1;
struct Dsu
{
    std::array<int,maxn>par;
    Dsu()
    {
        for(int i=0;i<maxn;i++)par[i]=i;
    }
    int find(int x)
    {
        if(x==par[x])return x;
        else return par[x]=find(par[x]);
    }
    void unite(int x,int y)
    {
        x=find(x),y=find(y);
        if(x!=y)par[y]=x;
    }
    bool same(int x,int y){return find(x)==find(y);}
};
std::array<int,maxn>num,odd,d;
int n,m;
int main()
{
    while(std::cin>>n>>m)
    {
        Dsu dsu;
        std::memset(&num,0,sizeof(num));
        std::memset(&odd,0,sizeof(odd));
        std::memset(&d,0,sizeof(d));
        for(int i=0,u,v;i<m;i++)
        {
            std::cin>>u>>v;
            d[u]++;d[v]++;
            dsu.unite(u,v);
        }
        for(int i=1;i<=n;i++)
        {
            num[dsu.find(i)]++;
            if(d[i]&1)odd[dsu.find(i)]++;
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(num[i]<=1)continue;
            if(!odd[i])ans++;
            else ans+=odd[i]/2;
        }
        std::cout<<ans<<"\n";
    }
    return 0;
}

 

 输出一个欧拉图的可行路径

P7771 【模板】欧拉路径 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

由于是有向图,题目也要求判断是否存在欧拉路

注意到由于题目需要字典序最小的欧拉路径

则对G[u]的所有邻接点排序

在dfs寻找欧拉路的时候,

利用当前点数组cur[u],

由于得到的欧拉路径是逆序的,逆向输出即可

在有向图判断起点,终点的时候,

出度-入度=1,的是起点,入度-出度=1的是终点

但如果都是偶点(出度==入度),任意起终点都可

#include<bits/stdc++.h>
const int maxn=1e5+1e1;
std::vector<int>G[maxn];
std::array<int,maxn>cur;
int d[maxn][2];
int n,m;
int s,t;
std::vector<int>ans;
void dfs(int u)
{
    for(int v=cur[u];v<(int)G[u].size();v=cur[u])
    {
        cur[u]=v+1;
        dfs(G[u][v]);
    }
    ans.emplace_back(u);
}
int main()
{
    s=1;
    std::cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++)
    {
        std::cin>>u>>v;//u->v
        //出度:以u为起点
        //入度:以v为终点
        d[u][1]++;d[v][0]++;
        G[u].emplace_back(v);
    }
    for(int i=1;i<=n;i++)std::sort(G[i].begin(),G[i].end());
    bool flag=true;
    int cnt[2]={0,0};
    for(int i=1;i<=n;i++)
    {
        if(d[i][1]!=d[i][0])
        {
            flag=false;
        }
        if(d[i][1]-d[i][0]==1)
        {
            cnt[1]++;
            s=i;
        }
        if(d[i][0]-d[i][1]==1)
        {
            cnt[0]++;
        }
    }
    if((!flag)&&!(cnt[0]==cnt[1]&&cnt[0]==1))
    {
        std::cout<<"No\n";
        return 0;
    }
    dfs(s);
    for(auto i=ans.rbegin();i!=ans.rend();i++)
    {
        std::cout<<*i<<" ";
    }
    std::cout<<"\n";
    return 0;
}

 单词 Play on Words - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题就是char转换一下到int,然后有向图判定有无欧拉路径即可

#include<bits/stdc++.h>
const int maxn=30;
struct Dsu
{
    std::array<int,maxn>par;
    Dsu()
    {
        for(int i=0;i<maxn;i++)par[i]=i;
    }
    int find(int x)
    {
        if(par[x]==x)return x;
        else return par[x]=find(par[x]);
    }
    void unite(int x,int y)
    {
        x=find(x),y=find(y);
        if(x!=y)par[y]=x;
    }
    bool same(int x,int y){return find(x)==find(y);}
};
int n;
std::array<std::array<int,2>,maxn>d;
std::array<int,30>vis;
int main()
{
    int t;std::cin>>t;
    while(t--)
    {
        std::memset(&d,0,sizeof(d));
        std::memset(&vis,0,sizeof(vis));
        Dsu dsu;
        std::cin>>n;
        std::string s;
        for(int i=0;i<n;i++)
        {
            std::cin>>s;
            int u=*s.begin()-'a';
            int v=*(s.end()-1)-'a';
            if(!vis[u])vis[u]=1;
            if(!vis[v])vis[v]=1;
            dsu.unite(u,v);
            d[u][1]++;d[v][0]++;
        }
        int cur=0;
        for(int i=0;i<26;i++)
        {
            if(vis[i])
            {
                if(dsu.par[i]==i)cur++;
            }
        }
        if(cur!=1)
        {
            std::cout<<"The door cannot be opened.\n";
            continue;
        }
        bool flag=true;
        int cnt[2]={0,0};
        for(int i=0;i<26;i++)
        {
            if(!vis[i])continue;
            if(d[i][1]!=d[i][0])flag=false;
            if(d[i][1]-d[i][0]==1)cnt[1]++;
            if(d[i][0]-d[i][1]==1)cnt[0]++;
        }
        if((!flag)&&!(cnt[0]==cnt[1]&&cnt[0]==1))
        {
            std::cout<<"The door cannot be opened.\n";
        }
        else std::cout<<"Ordering is possible.\n";
    }
    return 0;
}

 

posted @ 2022-11-07 15:16  惣聪术  阅读(78)  评论(0)    收藏  举报