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;
}