欧拉回路(项链,UVA 10054)

看来自己的知识水平还是很低的,需要更多的更大量的学习才行。


很容易想到建边图找欧拉回路。

然后死于不会找欧拉回路。

存在欧拉回路==从任意一点出发都能找到欧拉回路!=随便走都能走出欧拉回路。

因为走着走着出现了桥这种东西,就不能随便走了,如果走了就一去不复还了

尝试用随便走+贪心,但是没法解决的。

记得以前在《算法与数据结构》上看到要先找桥,然后如果不是万不得已就不要选桥。找桥还要用tarjan,妈呀,这也太麻烦了吧。

果然有很棒的解决方法。

紫书P169上的模板代码。

递归然后逆序输出保证每次都能回到当前节点。

而不是主动出去找。

思路十分巧妙


几个需要注意的地方:

①欧拉回路是每条边恰走一次,本题是每个珍珠恰用一次,所以要把珍珠当成边,颜色当成点,然后建图。

②珍珠可以翻转,所以图是无向图。

③本题没说珍珠不重复,说明建的图是可能有重边的,所以不能只标记连通,还要标记有多少次连通。

④无向图存在欧拉回路的充要条件是图连通且各点度数为偶数。别忘了检验图连通。只不过本题没有卡你这个罢了。


代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 55;
const int maxm = 1010;

int M;
int de[maxn];
int MAP[maxn][maxn];

void euler(int u)
{
    for(int v=0;v<maxn;v++) if(MAP[u][v])
    {
        MAP[u][v]--;
        MAP[v][u]--;
        euler(v);
        printf("%d %d\n",v,u);
    }
}

bool ok()
{
    for(int i=0;i<maxn;i++)
        if(de[i]&1)
            return false;
    return true;
}

void print()
{
    int now=0;
    while(!de[now]) now++;
    euler(now);
}

int main()
{
    int T,u,v;
    scanf("%d",&T);
    for(int t=1;t<=T;t++)
    {
        memset(de,0,sizeof(de));
        memset(MAP,0,sizeof(MAP));
        scanf("%d",&M);
        while(M--)
        {
            scanf("%d %d",&u,&v);
            de[u]++;
            de[v]++;
            MAP[u][v]++;
            MAP[v][u]++;
        }
        printf("Case #%d\n",t);
        if(ok()) print();
        else puts("some beads may be lost");
        if(t<T) puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值