Codeforces Round #550 (Div. 3) F. Graph Without Long Directed Paths

F. Graph Without Long Directed Paths

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a connected undirected graph consisting of nn vertices and mm edges. There are no self-loops or multiple edges in the given graph.

You have to direct its edges in such a way that the obtained directed graph does not contain any paths of length two or greater (where the length of path is denoted as the number of traversed edges).

Input

The first line contains two integer numbers nn and mm (2≤n≤2⋅1052≤n≤2⋅105, n−1≤m≤2⋅105n−1≤m≤2⋅105) — the number of vertices and edges, respectively.

The following mm lines contain edges: edge ii is given as a pair of vertices uiui, vivi (1≤ui,vi≤n1≤ui,vi≤n, ui≠viui≠vi). There are no multiple edges in the given graph, i. e. for each pair (ui,viui,vi) there are no other pairs (ui,viui,vi) and (vi,uivi,ui) in the list of edges. It is also guaranteed that the given graph is connected (there is a path between any pair of vertex in the given graph).

Output

If it is impossible to direct edges of the given graph in such a way that the obtained directed graph does not contain paths of length at least two, print "NO" in the first line.

Otherwise print "YES" in the first line, and then print any suitable orientation of edges: a binary string (the string consisting only of ‘0‘ and ‘1‘) of length mm. The ii-th element of this string should be ‘0‘ if the ii-th edge of the graph should be directed from uiui to vivi, and ‘1‘ otherwise. Edges are numbered in the order they are given in the input.

Example

input

Copy

6 5
1 5
2 1
1 4
3 1
6 1

output

Copy

YES
10100

这个题的题意就是修改一些边的方向让有向图不包含长度为2或更大的任何路径(其中路径长度表示为遍历边的数量),修改的边标记为1,没修改的标记为0,最后按顺序输出所有的边的标记
如下图

思路在下面代码的注释中

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxn=2e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int first[maxn],sign;
int vis[maxn];
int a[maxn][2];
struct node
{
    int to,w,next;
} edge[maxn<<1];
void init()
{
    for(int i = 0; i <=n; i++)
        first[i]=-1;
    sign=0;
}
void add_edge(int u,int v,int w)
{
    edge[sign].to=v;
    edge[sign].w=w;
    edge[sign].next=first[u];
    first[u]=sign++;
}
bool flag1=0;
void dfs(int x,int flag)///对整个图进行染色1 0 1 0...,
{
    vis[x]=flag;
    for(int i=first[x]; ~i; i=edge[i].next)
    {
        int to=edge[i].to;
        if(vis[to]==vis[x])///判断是是否有环
        {
            flag1=1;
            return ;
        }
        if(vis[to]==-1)
        {
            dfs(to,flag^1);
        }
    }
    return ;

}
int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=1; i<=m; i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add_edge(u,v,1);
        add_edge(v,u,1);
        a[i][0]=u;
        a[i][1]=v;
    }
    memset(vis,-1,sizeof(vis));
    dfs(1,1);
    if(flag1)
        puts("NO");///如果图中有环的话,肯定就会存在dist>=2的点,可以自己画一个三角形看看,就很容易理解了
    else
    {
        puts("YES");
        for(int i=1; i<=m; i++)
        {
            if(vis[a[i][0]]==1)///a[i][0]为第i条边的起点,a[i][1]为第i条边的终点。
                              ///这里我们已经将整个图染色,整个图分为两类,标记为1的点和标记为0的点
                              ///以标记为1的点为起点,出发的边不做修改,即边的标记为0
                              ///以标记为0的点为起点,出发的边改为相反的方向,即边的标记为1,
                              ///这里其实是不难理解的,两个相邻的点必定为1 0或者0 1,1->0->1
                              ///(1出发的边保持原来的方向,0出发的边改为相反的方向)或者(0出发
                              ///的边保持原来的方向,1出发的边改为相反的方向)才能使得整个图的不出现长度为2或者更大的路径
                printf("0");
            else
                printf("1");
        }
    }

    return 0;
}


原文地址:https://www.cnblogs.com/yuanlinghao/p/10638025.html

时间: 2024-10-09 17:25:19

Codeforces Round #550 (Div. 3) F. Graph Without Long Directed Paths的相关文章

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/contest/988/problem/E Description Polycarp lives on a coordinate line at the point x=0. He goes to his friend that lives at the point x=a. Polycarp can

Codeforces Round #501 (Div. 3) F. Bracket Substring

题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60949 ....看不懂 设dp[i][j][l]表示前i位,左括号-右括号=j,匹配到l了 状态转移,枚举下一个要填的括号,用next数组求状态的l,分别转移 代码 #include<bits/stdc++.h> using namespace std; const int maxn = 207;

Codeforces Round #392 (Div. 2) F. Geometrical Progression

原题地址:http://codeforces.com/contest/758/problem/F F. Geometrical Progression time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output For given n, l and r find the number of distinct geometrical pro

Codeforces Round #531 (Div. 3) F. Elongated Matrix(状压DP)

F. Elongated Matrix 题目链接:https://codeforces.com/contest/1102/problem/F 题意: 给出一个n*m的矩阵,现在可以随意交换任意的两行,最后从上到下,从左到右形成一个序列s1,s2.....snm,满足对于任意相邻的两个数,它们差的绝对值的最大值为k. 现在问怎么交换行与行,可以使得最后的这个k最大. 题解: 人生中第一道状压dp~其实还是参考了这篇博客:https://blog.csdn.net/CSDNjiangshan/art

Codeforces Round #548 (Div. 2) F splay(新坑) + 思维

https://codeforces.com/contest/1139/problem/F 题意 有m个人,n道菜,每道菜有\(p_i\),\(s_i\),\(b_i\),每个人有\(inc_j\),\(pref_j\),一个人可以买一道菜的条件是 1. \(p_i \leq inc_j \leq s_i\) 2. \(|b_i - pref_j| \leq inc_j-p_i\) ,问每个人分别能买多少道菜 题解 转化一下公式 \(p_i \leq inc_j \leq s_i\) 下面两个满

Codeforces Round #549 (Div. 2) F 数形结合 + 凸包(新坑)

https://codeforces.com/contest/1143/problem/F 题意 有n条形如\(y=x^2+bx+c\)的抛物线,问有多少条抛物线上方没有其他抛物线的交点 题解 \(y=x^2+bx+c=>y+x^2=bx+c\),转换为点\((x,y+x^2)\)在bx+c的直线上 两个点确定一条抛物线,同时也确定了一条直线 需要选择最上面那些点相邻确定的抛物线,所以维护一个上凸包即可 维护上凸包,当前点在前进方向左边需要向后退,cross(a,b)>=0 代码 #inclu

Codeforces Round #530 (Div. 2)F Cookies (树形dp+线段树)

题:https://codeforces.com/contest/1099/problem/F 题意:给定一个树,每个节点有俩个信息x和t,分别表示这个节点上的饼干个数和先手吃掉这个节点上一个饼干的的时间.然后有先手和后手俩个人. ?先手可以这么操作:在规定总时间T到达某个节点然后一定要返回根节点1,期间可以选择吃掉某些节点上的某些饼干(前提是保证剩下的时间能够回到根节点): ?后手可以这么操作:在先手到达的位置和这个位置的孩子之间的连边选择一条让先手吃得更多的边摧毁掉,也可以跳过这个过程: 问

Codeforces Round #615 (Div. 3) F. Three Paths on a Tree

F. Three Paths on a Tree 原题链接:https://codeforces.com/contest/1294/problem/F 题目大意: 给定一棵树,选出三点,使三点连成的j简单路径最大.简而言之,三个点连成的边的集合大小. 解题思路: 假设任取一点为三点连线的公共点,最长路径就是这个点到其他三个点的三条最长边之和,可知这个点一定在直径上(画图分析假设不在时的最长路径可反证).所以先求出树的直径,在使用$ans =(a b+a c+b c) / 2$遍历可以得到第三个点

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以