【Codeforces Round #589 D】Complete Tripartite

Topic Link

Complete Tripartite

introduce

You have a simple undirected graph consisting of \(n\) vertices and \(m\) edges. The graph doesn't contain self-loops, there is at most one edge between a pair of vertices. The given graph can be disconnected.
Let's make a definition.
Let \(v_1\) and \(v_2\) be two some nonempty subsets of vertices that do not intersect. Let \(f(v_1,v_2)\) be true if and only if all the conditions are satisfied:

  1. There are no edges with both endpoints in vertex set \(v_1\).
  2. There are no edges with both endpoints in vertex set \(v_2\).
  3. For every two vertices \(x\) and \(y\) such that \(x\) is in \(v_1\) and \(y\) is in \(v_2\), there is an edge between \(x\) and \(y\).
    Create three vertex sets \((v_1, v_2, v_3)\) which satisfy the conditions below;
  4. All vertex sets should not be empty.
  5. Each vertex should be assigned to only one vertex set.
  6. \(f(v_1,v_2)\), \(f(v_2,v_3)\), \(f(v_3,v_1)\) are all true.
    Is it possible to create such three vertex sets? If it's possible, print matching vertex set for each vertex.

    Input

    The first line contains two integers \(n\) and \(m\) \((3≤n≤10^5, 0≤m≤min(3⋅10^5,\frac{n(n−1)}{2}) )\) — the number of vertices and edges in the graph.
    The \(i\)-th of the next \(m\) lines contains two integers \(a_i\) and \(b_i\) \((1≤a_i<b_i≤n)\) — it means there is an edge between \(a_i\) and \(b_i\). The graph doesn't contain self-loops, there is at most one edge between a pair of vertices. The given graph can be disconnected.

    Output

    If the answer exists, print \(n\) integers. \(i\)-th integer means the vertex set number (from \(1\) to \(3\)) of \(i\)-th vertex. Otherwise, print \(−1\).
    If there are multiple answers, print any.

    Examples

    input

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

    output

    1 2 2 3 3 3 
    

    input

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

    output

    -1
    

    Note

    In the first example, if \(v_1={1}\), \(v_2={2,3}\), and \(v_3={4,5,6}\) then vertex sets will satisfy all conditions. But you can assign vertices to vertex sets in a different way; Other answers like "2 3 3 1 1 1" will be accepted as well.

    In the second example, it's impossible to make such vertex sets.

    answer

    The meaning of the questions requires a point on the graph is not divided into three sets of loopback, required points in each set have not connected to side, and each should have a point and all points within the set has two additional side is connected to a .
    I thought the first set of each point can be violent enumeration, see if you can put each are assigned to a collection point where, along with some optimization in the process of enumeration.
    In determining whether a point when the current collection, I enumerate a bit this point of each edge, and if there is even the point of the current collection side, it \ (return 0; \) .
    I \ (as [j] \) to represent \ (j \) at this point in the current set of numbers.
    Then \ (ss [j] \) that number is \ (j \) is the number of points in the set, with \ (ss [j] \) to determine all the points outside the current point itself and whether there is even a set of edges (points outside the edge determination and enumeration set itself even number of sides is equal to the set point and the other two).
    Just find a set of set of viable distribution scheme, it can output the program, the program is ended.
    When complete enumeration of all the points program can not be found, then output \ (--1 \) .
    On the code:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int x,y;
struct aa{
    int to,nxt;
}p[600009];
int h[300009],len;
void add(int x,int y){
    if(y>=x) return;//每个点判断在那个集合时已在集合里的点的序号一定都小于这个点,所以指向序号大的点的边对于判断集合没有影响。
    p[++len].to=y;
    p[len].nxt=h[x];
    h[x]=len;
}
int as[300009];
int ss[9];
bool pd(int x,int uu){
    int s=0;
    for(int j=h[x];j;j=p[j].nxt){
        if(p[j].to>=x) continue;
        if(as[p[j].to]==uu) return 0;
        else s++;
    }
    if(s!=x-1-ss[uu]) return 0;
    return 1;
}
int l=1;
void dfs(int u){
    if(u==n+1){
        if(ss[3]==0 || ss[2]==0 || ss[1]==0) return;
        for(int j=1;j<=n;j++)
            printf("%d ",as[j]);
        exit(0);
    }
    for(int j=1;j<=l;j++)//因为当两个集合都为空时两个集合的序号没有区别,所以这里做了点优化(实际上也减少不了多少时间)
        if(pd(u,j)){
            as[u]=j;
            ss[j]++;
            bool mmm=0;
            if(l<=2 && ss[l]>0){
                mmm=1;
                l++;
            }
            dfs(u+1);
            l-=mmm;
            ss[j]--;
        }
}
int main() {
    scanf("%d%d",&n,&m);
    for(int j=1;j<=m;j++){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(1);
    printf("-1");
    return 0;
}

Guess you like

Origin www.cnblogs.com/linjiale/p/11613242.html