【JZOJ 1319】邮递员(欧拉回路)

Description

给出一张图,求一条路径,使得每个点和每条边都被访问至少一次,并输出这条路径,如有多条,则输出字典序最小的。
保证每个点被连了2,4或8次(自环算2次),有重边。

Solution

很显然,每条边都在环中,且可以有一种方案使得每个环都不相交,
有两种方法:

每走一条边,把当前边删掉,跑tarjan判断桥边,如果当前点连出的边有不是桥边的,则走不是桥边的,否则走桥边;
再加上字典序判断即可,
复杂度: O(m(n+m))

从1号点开始,先按字典序最小的不停走,直到走回点1,记录路径,
从路径最后一个开始,看看这个点还能不能继续走,如可以则继续走,把新增路径插入原来的路径

复杂度: O(n)

这里提供的是思路,这两种思路都挺好的。

Code

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=205;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n;
int B[N][N*N];
int bc[N][N];
int b1[N];
int ans[N*N],d[N*N];
bool PX(int q,int w){return q>w;}
void dfs(int q)
{
    for(int Q=q;(Q!=q||!d[0])&&B[q][0]>=0;)
    {
        if(bc[q][B[q][B[q][0]]])
        {
            d[++d[0]]=q;
            bc[q][B[q][B[q][0]]]--;
            bc[B[q][B[q][0]]][q]--;
            B[q][0]--;
            q=B[q][1+B[q][0]];
        }else B[q][0]--;
    }
}
int main()
{
    int q,w;
    read(n),read(m);
    fo(i,1,n)read(q);
    fo(i,1,m)
    {
        read(q),read(w);
        b1[q]++,b1[w]++;
        B[q][++B[q][0]]=w;
        B[w][++B[w][0]]=q;
        bc[q][w]++,bc[w][q]++;
    }
    fo(i,1,n)sort(B[i]+1,B[i]+1+B[i][0],PX);
    printf("%d\n",m);
    if(!m)return 0;
    ans[0]=ans[1]=1;
    for(q=1;q>0;q--)
    {
        d[0]=0;
        dfs(ans[q]);
        if(d[0]>=1)
        {
            fod(i,ans[0],q)ans[i+d[0]]=ans[i];
            fo(i,q,q+d[0]-1)ans[i]=d[i-q+1];
            ans[0]+=d[0];
            q+=d[0]+1;
        }
    }
    fo(i,1,ans[0])printf("%d ",ans[i]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值