sgu 101 Domino 欧拉通路

11 篇文章 0 订阅

  题意是给若干多米若骨牌,每张牌两侧有数字,两张牌在面对面数字相同的情况下可以放在一起,求一中摆放方式..把每张牌看成一条边,连接这张牌牌两侧的数字表示的节点..这样就是一个球欧拉通路的问题了...另外注意判断一下无解,还有搜完欧拉通路后,判断一下是不是所有的边都用上了,否则就是存在不连通的情况..

   

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
using namespace std;
struct node
{
    int adv,num;
    node()
    {

    }
    node(int p,int q)
    {
        adv=p;
        num=q;
    }
};
vector <node>ans;
vector <node> g[10];
vector <int>a[10][10];
int cnt[10][10];
int n,m,p,q;
int tot;
bool vis[300];
void euler(int u)
{
    for (int j=0; j<g[u].size(); j++)
    {
        int v=g[u][j].adv;
        if (!vis[g[u][j].num])
        {
            vis[g[u][j].num]=true;
            euler(v);
//            cout<<u<<" "<<v<<endl;
            ans.push_back(node(u,v));
        }
    }

}
int deg[10];
int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d",&n);
    memset(cnt,0,sizeof cnt);
    memset(vis,false,sizeof vis);
    memset(deg,0,sizeof deg);

    tot=0;
    for (int i=1; i<=n; i++)
    {
        scanf("%d%d",&p,&q);
        deg[p]++;
        deg[q]++;
        a[p][q].push_back(i);
        g[p].push_back(node(q,tot));
        g[q].push_back(node(p,tot++));
    }
    int sum=0;
    int st;
    for (int i=0; i<7; i++)
    if (deg[i]&1)
    {
        sum++;
        st=i;
    }
    if (sum==0)
    {
        for (int i=0; i<7; i++)
        if (deg[i]!=0)
        {
            st=i;
            break;
        }
    }
    else
    if (sum>2)
    {
        puts("No solution");
        return 0;
    }

    euler(st);
    sum=0;

    for (int i=0; i<tot; i++)
    if (!vis[i])
    {
        puts("No solution");
        return 0;
    }

    memset(vis,0,sizeof vis);
    for (int i=ans.size()-1; i>=0; i--)
    {
        p=ans[i].adv;
        q=ans[i].num;
        bool ft=false;
        for (int i=0; i<a[p][q].size(); i++)
        if (!vis[a[p][q][i]])
        {
            printf("%d +\n",a[p][q][i]);
            vis[a[p][q][i]]=true;
            ft=true;
            break;
        }
        if (ft) continue;
        for (int i=0; i<a[q][p].size(); i++)
        {
            if (!vis[a[q][p][i]])
            {
                printf("%d -\n",a[q][p][i]);
                vis[a[q][p][i]]=true;
                ft=true;
                break;
            }
        }
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值