Codeforces 405E DFS

这个题目要求把一个无向连通图里面的所有边,分成 两个一对,只能出现一次,而且一对边必须是连在一起的,点可以复用  但边不可复用

可解条件很易得,因为图是连通的,只要边数为偶数即可。

一开始我借着做欧拉回路的方法,直接DFS暴搜,沿路做标记,遇到未标记的连续两条边 输出即可

不过 事实证明这个算法是错的

暴搜能成立只是建立在图上的边可以存在很多个边对里,但肯定有图不满足这种条件

其实解决方法也就是在DFS的基础上对特殊边进行下考虑即可

即每次对某个点,对子节点进行dfs,如果发现子节点下面有落单的边,则将当前边和子节点的落单边组合起来 输出

否则就把当前边存进该点独有的队列中,全部存完后,两两进行输出,如果有落单边,给父亲返回,告诉他这里有落单边 即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N=100000+10;
int u[N<<1],v[N<<1],nt[N<<1],ft[N];
int n,m,cnt;
int vis[N<<1];
void add(int a,int b)
{
    u[cnt]=a;
    v[cnt]=b;
    nt[cnt]=ft[a];
    ft[a]=cnt++;
}
int dfs(int x,int f)
{
    queue<int> vec;
    for (int i=ft[x];i!=-1;i=nt[i]){
        int nx=v[i];
        if (vis[i] || nx==f) continue;
        vis[i]=vis[i^1]=1;
        int r=dfs(nx,x);
        if (r){
            printf("%d %d %d\n",x,nx,r);
        }
        else{
            vec.push(nx);
        }
    }
    while (vec.size()>=2){
        int a=vec.front();
        vec.pop();
        int b=vec.front();
        vec.pop();
        printf("%d %d %d\n",a,x,b);
    }
    if (!vec.empty()){
        int a=vec.front();
        vec.pop();
        return  a;
    }
    return 0;
}
int main()
{
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        cnt=0;
        memset(ft,-1,sizeof ft);
        memset(vis,0,sizeof vis);
        int a,b;
        for (int i=0;i<m;i++){
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        //cout<<m<<" "<<(m&1)<<endl;
        if (m&1){
            puts("No solution");
            continue;
        }
        dfs(1,-1);
    }
    return 0;
}

Codeforces 405E DFS,布布扣,bubuko.com

时间: 2024-12-27 15:28:22

Codeforces 405E DFS的相关文章

Fox And Two Dots codeforces 510B(DFS)

http://codeforces.com/problemset/problem/510/B 题意:问你能否用相同的字母构成一个环. 分析:每一个都直接从它自身开始,看看到最后是否还能回到它本身.(注意:需要最少4个点) #include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <vector> #include <algori

CodeForces 510B DFS水题

题目大意:在图中找到一个字符可以围成一个环(至少有环四个相同元素) 题目思路:对当前点进行搜索,如果发现可以达到某个已经被查找过的点,且当前点不是由这个点而来,则查找成功. #include<cstdio> #include<stdio.h> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<cstring>

CodeForces 570D DFS序 树状数组 Tree Requests

参考九野巨巨的博客. 查询一个子树内的信息,可以通过DFS序转成线形的,从而用数据结构来维护. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 #define MP make_pair 7 #define FI first 8 #define SE second 9 using name

Codeforces - 440C DFS

搜索苦手,注意正负 #include<bits/stdc++.h> #define rep(i,j,k) for(int i = j; i <=k; i++) using namespace std; const int maxn = 55; typedef long long ll; ll one[maxn]; ll n; ll dfs(ll n,ll i){ ll k = n/one[i]; ll j = n%one[i]; if(j==0) return k*i; return k

Codeforces 937D dfs

D. Sleepy Game 题意:n 个点 , m 条边的有向图.有两个人 A .B ,芯片开在点 s ,两人轮流移动芯片,A 为先手,最后不能移动者输. 但 B 在睡觉,所以 B 的移动由 A 帮他移. 问 A 是否能赢.如能,输出路径 :如不能,输出是否可以 平局 或 输. tags: 每个点两种状态 : 能到这个点且轮到 A 走,能到这个点且轮到B走. 用 pre[i][2] 表示这两种状态的前一个点,dfs 搜索状态,如果能到入度为 0 点,且轮到 B 走,那就赢了.如果不能赢就看是否

Concise and clear CodeForces - 991F(dfs 有重复元素的全排列)

就是有重复元素的全排列 #include <bits/stdc++.h> #define mem(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long LL; const int maxn = 10010, INF = 0x7fffffff; char str[maxn]; int vis[maxn], v[maxn]; LL num[maxn]; LL res = 0; void init() { num[0

Codeforces 1110F(DFS序+线段树)

题面 传送门 分析 next_id = 1 id = array of length n filled with -1 visited = array of length n filled with false function dfs(v): visited[v] = true id[v] = next_id next_id += 1 for to in neighbors of v in increasing order: if not visited[to]: dfs(to) 观察题目中的

E - Mahmoud and Ehab and the bipartiteness CodeForces - 862B (dfs黑白染色)

Mahmoud and Ehab continue their adventures! As everybody in the evil land knows, Dr. Evil likes bipartite graphs, especially trees. A tree is a connected acyclic graph. A bipartite graph is a graph, whose vertices can be partitioned into 2 sets in su

Codeforces 348B:Apple Tree(DFS+LCM+思维)

http://codeforces.com/contest/348/problem/B 题意:给一棵树,每个叶子结点有w[i]个苹果,每个子树的苹果数量为该子树所有叶子结点苹果数量之和,要使得每个结点的各个子树苹果数量相等,求至少需要拿走的苹果数量. 思路:一开始以为只要使得所有子树之和相同就行了. 1 void dfs(int u, int fa) { 2 int num = 0, mi = INF; 3 for(int i = head[u]; ~i; i = edge[i].nxt) {