ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Cf #434 Div.1 D Wizard's Tour [构造题]

2019-08-30 19:39:14  阅读:357  来源: 互联网

标签:度数 int Wizard Cf vis Tour maxn 使用 2n


WizardsTourWizard's TourWizard′sTour


\color{blue}{最初想法}最初想法

考虑枚举每个边 (u,v)(u, v)(u,v), 设 uuu 连出的点中度数最小的点为 aaa, vvv 连出的点中度数最小的点为 bbb,
比较 u,au, au,a 与 v,bv, bv,b 的度数和大小, 贪心地选取度数较小的点, 得到一个三元路径,
使用 multisetmultisetmultiset 维护度数, 枚举边按以上方法找路径即可 .
代码纪念


\color{red}{正解部分}正解部分

先从图中剥离出一颗树, 然后 DFSDFSDFS, 从底向顶处理, 设当前节点为 iii, 度数为 cnticnt_icnti​,

  • cnticnt_icnti​ 为偶数 2n2n2n , 则直接转化为 nnn 条路径 .
  • cnticnt_icnti​ 为奇数 2n12n-12n−1, 则连向父亲的边保存, 其余构成 (2n2)/2(2n-2)/2(2n−2)/2 条路径 .

这样构造, 可以使得最后至多留下一条边, 这条边是连向根节点的 .


\color{red}{实现部分}实现部分

DFSDFSDFS 到一个点 kkk 时, 其连出去的点包含以下类型 \downarrow

  • 儿子
  1. 使用了与父亲相连的边的儿子
  2. 没有使用 …
  • 父亲
  1. 需要使用与父亲相连的边
  2. 不需要 …
  • 非子非父
  1. 已经连过边
  2. 没有…

  • 注意根节点没有父亲 .
  • 可以使用类似网络流的建图方式删边 .
  • 使用标记数组 vis[]vis[]vis[] 辅助建树 .
  • 使用标记数组 usefa[]use_fa[]usef​a[] 记录是否使用了 fafafa 的边 .
#include<bits/stdc++.h>
#define reg register
#define pb push_back

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 200005;

int N;
int M;
int num0;
int A_cnt;
int cnt[maxn];
int vis[maxn];
int head[maxn];
int Ans[maxn][3];
int use_fa[maxn];

std::vector <int> A[maxn];

struct Edge{ int nxt, to; } edge[maxn<<1];

void Add(int from, int to){
        edge[++ num0] = (Edge){ head[from], to };
        head[from] = num0;
}

void DFS(int k, int fa, int have_fa){ 
        vis[k] = 1;
        for(reg int i = head[k]; i; i = edge[i].nxt){
                int to = edge[i].to;
                if(!to) continue ;
                edge[i].to = edge[i^1].to = 0;
                if(!vis[to]){ 
                        DFS(to, k, 1);
                        if(!use_fa[to]) A[k].pb(to); // to使用了与父亲k相连的边
                }else A[k].pb(to);
        }
        if(have_fa) A[k].pb(fa);
        int size = A[k].size();
        if(size <= 1) return ;
        use_fa[k] = !(size & 1);
        for(reg int i = 0; i+1 < size; i += 2)
                Ans[++ A_cnt][0] = A[k][i], Ans[A_cnt][1] = k, Ans[A_cnt][2] = A[k][i+1]; 

}

int main(){
        N = read(), M = read();
        num0 = 1;
        for(reg int i = 1; i <= M; i ++){
                int u = read(), v = read();
                Add(u, v), Add(v, u);
        }
        for(reg int i = 1; i <= N; i ++) if(!vis[i]) DFS(i, 0, 0);
        printf("%d\n", A_cnt);
        for(reg int i = 1; i <= A_cnt; i ++) printf("%d %d %d\n", Ans[i][0], Ans[i][1], Ans[i][2]);
        return 0;
}

标签:度数,int,Wizard,Cf,vis,Tour,maxn,使用,2n
来源: https://blog.csdn.net/Zbr162/article/details/100160111

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有