1. 程式人生 > 實用技巧 >[CF662B]Graph Coloring

[CF662B]Graph Coloring

題目

傳送門

題解

首先,意識到每一個連通塊都是獨立的,那麼我們可以分每個聯通塊進行考慮.

對於每一個連通塊,如果我們需要確定這個塊的反轉情況,我們只需要知道兩個條件:

  1. 某一個點的反轉情況;
  2. 所有邊最終會被翻成什麼顏色;

因為這兩個情況的組合至多有 \(2\times 2=4\) 種情況,而每個連通塊,如果我們要確定其顏色,只需要 \(dfs\) 一遍,複雜度 \(\mathcal O(n)\),那麼總共的複雜度為 \(\mathcal O(4n)\),是可過的

所以,我們只需要對於每一個連通塊,假定其中任意一點的反轉情況,再列舉所有邊染成的顏色,然後 \(dfs\) 檢查是否可行,選擇最小的反轉方法即可

程式碼

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

#define rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i)
#define erep(i,u) for(signed i=tail[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
typedef long long LL;
// typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef unsigned uint;
#define Endl putchar('\n')
// #define int long long
// #define int unsigned
// #define int unsigned long long

#define cg (c=getchar())
template<class T>inline void read(T& x){
    char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T>inline T read(const T sample){
    T x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T>void fwrit(const T x){//just short,int and long long
    if(x<0)return (void)(putchar('-'),fwrit(-x));
    if(x>9)fwrit(x/10);
    putchar(x%10^48);
}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
    inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
    return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}

const int MAXN=100000;
const int MAXM=100000;
const int INF=(1<<30)-1;

struct edge{int to,nxt,c;}e[MAXM*2+5];
int tail[MAXN+5],ecnt;
inline void add_edge(const int u,const int v,const int c){
    e[++ecnt]=edge{v,tail[u],c};tail[u]=ecnt;
    e[++ecnt]=edge{u,tail[v],c};tail[v]=ecnt;
}
int n,m;

inline void Init(){
    n=read(1),m=read(1);
    int u,v;char ch[5];
    rep(i,1,m){
        scanf("%d %d %s",&u,&v,ch);
        add_edge(u,v,ch[0]=='R');
    }
}

int rever[MAXN+5];

void Clear(const int u){
    rever[u]=-1;
    for(int i=tail[u];i;i=e[i].nxt)if(rever[e[i].to]!=-1)
        Clear(e[i].to);
}

int Judge(const int u,const int rev,const int goal){
    int sum=rev,ret;
    rever[u]=rev;
    for(int i=tail[u],v,tore;i;i=e[i].nxt){
        v=e[i].to;
        tore=goal^e[i].c^rev;
        if(rever[v]!=-1 && rever[v]!=tore)return -1;
        if(rever[v]==-1){
            ret=Judge(v,tore,goal);
            if(ret==-1)return -1;
            sum+=ret;
        }
    }return sum;
}

int ans=INF,memo[MAXN+5];

signed main(){
    Init();
    int ans1,ans2,f1,f2;
    bool flg;
    rep(t,0,1){//列舉顏色
        flg=false;
        memset(rever,-1,sizeof rever);
        rep(i,1,n)if(rever[i]==-1){
            Clear(i),ans1=Judge(i,0,t);
            Clear(i),ans2=Judge(i,1,t);
            // printf("When i == %d, ans1 == %d, ans2 == %d\n",i,ans1,ans2);
            if(ans1==-1 && ans2==-1){flg=true;break;}
            if(ans2==-1 || ans1<ans2){
                Clear(i);
                Judge(i,0,t);
            }
        }
        if(!flg){
            int tot=0;
            rep(i,1,n)if(rever[i]==1)++tot;
            if(tot>(n/2)){
                tot=n-tot;
                rep(i,1,n)rever[i]=!rever[i];
            }
            if(tot<ans){
                ans=tot;
                rep(i,1,n)memo[i]=rever[i];
            }
        }
    }
    if(ans==INF)puts("-1");
    else{
        writc(ans,'\n');
        rep(i,1,n)if(memo[i])writc(i,' ');Endl;
    }
    return 0;
}
/*
6 6
1 2 R
1 3 R
2 3 R
4 5 B
4 6 B
5 6 B

ans == -1
*/