codeforces 858F&&JZOJ5404graph dfs

来源:互联网 发布:软件研发分包管理制度 编辑:程序博客网 时间:2024/05/18 20:52

题意:给定一张n个点m条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通
你想在这张图上进行若干次旅游,每次旅游可以任选一个点x作为起点,再走到一个与x 直接有边相连的点y,再走到一个与y 直接有边相连的点z 并结束本次旅游
作为一个旅游爱好者,你不希望经过任意一条边超过一次,注意一条边不能即正向走一次又反向走一次,注意点可以经过多次,在满足此条件下,你希望进行尽可能多次的旅游,请计算出最多能进行的旅游次数并输出任意一种方案
n<=2e5.

没看空间,无脑写了个1e5,挂成暴力,爽翻。
并不难的一道题(雾)。
首先把原图看作树形图,然后进行处理。
既然是一颗树,那么情况无非两种,一种是一条链,另外一种是山峰型。
为了保证最大化答案,我们从下往上开始填。
对于当前的一对点x,v,v为x的儿子,设这两个点和另外一个点z匹配成为答案。
由于从下往上匹配,保证z的深度比x小,等于v或者是v的儿子。
那么我们对于两种情况分开计算。
记录一个k,表示将要匹配的第三个点。
对于一个峰型点对,如果未能匹配成功,k记录v的兄弟。
对于一个链型点对,如果未能匹配成功,k记录v的儿子。
递归dfs返回k,即如果当前点未能匹配,能和当前点一起和匹配祖先的点。
如果v是已经走过的儿子,看看能否和k,x匹配,不可以的话就k=v,原理同上。

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=5e5+5;int n,m;int head[N],next[N],go[N];int dep[N],cnt,ans[4][N];int tot;inline int dfs(int x,int fa){    dep[x]=dep[fa]+1;int k=0;    for(int i=head[x];i;i=next[i])    {        int v=go[i];        if (!dep[v])        {            int z=dfs(v,x);            if (z)            {                ans[1][++cnt]=z;                ans[2][cnt]=v;                ans[3][cnt]=x;            }            else            {                z=v;                if (k)                {                    ans[1][++cnt]=z;                    ans[2][cnt]=x;                    ans[3][cnt]=k;                    k=0;                 }                else k=z;            }        }        else        if (dep[v]>dep[x])        {            int z=v;            if (z)            {                if (k)                {                    ans[1][++cnt]=z;                    ans[2][cnt]=x;                    ans[3][cnt]=k;                    k=0;                }                else k=z;            }        }    }    return k;}inline void add(int x,int y){    go[++tot]=y;    next[tot]=head[x];    head[x]=tot;}int main(){    scanf("%d%d",&n,&m);    fo(i,1,m)    {        int x,y;        scanf("%d%d",&x,&y);        add(x,y),add(y,x);    }    fo(i,1,n)if (!dep[i])dfs(i,i);    printf("%d\n",cnt);    fo(i,1,cnt)printf("%d %d %d\n",ans[1][i],ans[2][i],ans[3][i]);    return 0;}
阅读全文
0 0