Codeforces 1228D. Complete Tripartite

传送门

不妨设 $1$ 号点在集合 $1$ 里

那么对于其他点,有且只有所有和 $1$ 没有边的点都在集合 $1$ 里

考虑不在集合 $1$ 的任意一个点 $x$ ,不妨设它在集合 $2$ 里

那么所有不在集合 $1$ 的,和 $x$ 没有边的点都在集合 $2$ 里,剩下的点都一定在集合 $3$ 里

所以集合划分完毕,然后就是判断合法性了,特判当然是越多越好啦!

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) f=-1; ch=getchar(); }
    while(ch>=‘0‘&&ch<=‘9‘) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=6e5+7;
int n,m,bel[N],cnt[4];
int fir[N],from[N<<1],to[N<<1],cntt;
inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
int fa[N];
inline int find(int x) { return x!=fa[x] ? fa[x]=find(fa[x]) : x; }
int main()
{
    n=read(),m=read(); int a,b;
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++)
    {
        a=read(),b=read();
        add(a,b); add(b,a); fa[find(a)]=find(b);
    }
    bel[1]=1; cnt[1]++;
    for(int i=2;i<=n;i++)
    {
        bool GG=0;
        for(int j=fir[i];j;j=from[j])
        {
            int &v=to[j]; if(v==1) GG=1;
        }
        if(!GG&&!bel[i]) bel[i]=1,cnt[1]++;
    }
    int x=0;
    for(int i=fir[1];i;i=from[i])
    {
        x=to[i]; break;
    }
    bel[x]=2; cnt[2]++;
    for(int i=1;i<=n;i++)
    {
        bool GG=0; if(bel[i]) continue;
        for(int j=fir[i];j;j=from[j])
        {
            int &v=to[j]; if(v==x) GG=1;
        }
        if(!GG) bel[i]=2,cnt[2]++;
        else bel[i]=3,cnt[3]++;
    }
    for(int i=1;i<=3;i++) if(!cnt[i]) { printf("-1\n"); return 0; }
    if(cnt[1]*cnt[2]+cnt[2]*cnt[3]+cnt[1]*cnt[3]!=m) { printf("-1\n"); return 0; }
    for(int i=1;i<=n;i++)
    {
        if(find(i)!=find(1)) { printf("-1\n"); return 0; }
        int tot=0,res=0; if(!bel[i]) { printf("-1\n"); return 0; }
        for(int j=fir[i];j;j=from[j])
        {
            int &v=to[j]; if(bel[v]==bel[i]) { printf("-1\n"); return 0; }
            tot++;
        }
        for(int j=1;j<=3;j++) if(bel[i]!=j) res+=cnt[j];
        if(tot!=res) { printf("-1\n"); return 0; }
    }
    for(int i=1;i<=n;i++) printf("%d ",bel[i]);
    puts(""); return 0;
}

原文地址:https://www.cnblogs.com/LLTYYC/p/11612340.html

时间: 2024-10-15 08:22:06

Codeforces 1228D. Complete Tripartite的相关文章

Complete Tripartite

D - Complete Tripartite 思路:这个题是个染色问题.理解题意就差不多写出来一半了.开始的时候还想用离散化来储存每个点的状态,即它连接的点有哪些,但很无奈,点太多了,long long范围内肯定存不完,于是想到用python来写,但是 py 也没有很熟练.....便放弃了. 需要注意的: 要统计总共有多少颜色,不然会漏掉只有两种颜色的情况,这种情况是输出-1的.还有前向星存边的时候记得开两倍. 代码: // Created by CAD on 2019/10/2. #incl

Codeforces 1203F2 Complete the Projects (hard version)

[cf题面](https://codeforces.com/contest/1203/problem/F2 Time limit 2000 ms Memory limit 262144 kB 解题思路 先留坑,吃完饭来填 源代码 #include<cstdio> #include<algorithm> int n,r; struct Data{ int need,delta; bool operator < (const Data & a)const{ if(delt

Codeforces 1203F2 Complete the Projects (hard version)(dp)

啊,dp,万恶的dp. 本来不想补的,被某人押着说div3这么可以不ak于是不得不补了.真是痛苦的经历.(笑) 题目链接:https://codeforces.com/problemset/problem/1203/F2 题目大意:给定任务个数n和初始值r,完成每个任务需要有ai的r值,完成后r值会改变bi,问最多能完成多少任务(要保证最后r>=0) 思路:首先如果是正值的话自然按照a从小到大排一遍能加的都加上,然后问题在于负值.贪心显然不行,或者说这其实就是个背包问题的轻度转换,首先要做的预处

CodeForces - 1228D

乍一看,嗯,图论题,不错: 结果,这尼玛是模拟???? 传送链接:https://codeforces.com/contest/1228/problem/D 看了大佬的代码瞬间就明白了许多!!! #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<set> #define maxn 300

CodeForces 716B Complete the Word

留坑! 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=50000+2; 4 char ca[N]; 5 int main() 6 { 7 int i,j; 8 9 while(scanf("%s",ca)!=EOF) 10 { 11 12 if(strlen(ca)<26) 13 { 14 printf("-1\n"); 15 continue; 16 } 17 int

Codeforces 716D - Complete The Graph(最短路)

题意:给定n个点,m条边,以及起点s,终点t,问你图中是否存在s->t的最短路为L,其中权值为0的可以任意修改. 思路:对给定的边分为2类,权重不为0的直接扔进去建图,权重为0的边先存起来.接着跑一遍堆优化的dij,如果dis[t]小于L,那么无论怎么修改权重0的边都没有办法凑出最短路L: 如果dis[t]=L,那么直接输出:如果dis[t]>L,则将原来事先存起来的边一条一条的加进去,权值设为1.每加一条边就跑一次dij,一旦找到dis[t]<=L,就可以终止并输出. PS:原来堆优化

Codeforces 715B. Complete The Graph 最短路,Dijkstra,构造

原文链接https://www.cnblogs.com/zhouzhendong/p/CF715B.html 题解 接下来说的“边”都指代“边权未知的边”. 将所有边都设为 L+1,如果dis(S,T) < L ,那么必然无解. 将所有边都设为 1 ,如果 dis(S,T) > L ,那么必然无解. 考虑将任意一条边的权值+1,则 dis(S,T) 会 +0 或者 +1 . 如果将所有边按照某一个顺序不断+1,直到所有边的权值都是L+1了,那么在这个过程中,dis(S,T) 是递增的,而且一定

Codeforces 1203F1 Complete the Projects (easy version)

cf题面 Time limit 2000 ms Memory limit 262144 kB 解题思路 看见这题觉得贪心可做,那就贪吧.(昨天真是贪心的一天,凌晨才被这两道贪心题虐,下午多校又来,感觉我现在比赛时候想贪心就是瞎猜,猜出一个结论就想办法hack,想不出hack就交上去,然后WA,然后自闭,很难摸到门道) 下面这些是我的做题和思考过程-- 显然要先把能加rating和不掉rating的做了,而且要按照要求从低到高的顺序做,因为如果当前rating能满足要求高的,那也能满足要求低的,如

CodeForces - 1228D (暴力+思维+乱搞)

题意 https://vjudge.net/problem/CodeForces-1228D 有一个n个顶点m条边的无向图,在一对顶点中最多有一条边. 设v1,v2是两个不相交的非空子集,当满足以下条件时f(v1,v2)为真 v1中的点之间不存在边 v2中的点之间不存在边 对于在v1v2中的每一对顶点,x在v1中,y在v2中,xy之间有边 所有点集不为空,且不相交,是否有v1,v2,v3使得f(v1,v2).f(v2,v3).f(v3,v1)均为真 如果有输出每个点所在的点集(1,2,3),否则