[CF662B]Graph Coloring
阿新 • • 發佈:2020-07-27
題目
題解
首先,意識到每一個連通塊都是獨立的,那麼我們可以分每個聯通塊進行考慮.
對於每一個連通塊,如果我們需要確定這個塊的反轉情況,我們只需要知道兩個條件:
- 某一個點的反轉情況;
- 所有邊最終會被翻成什麼顏色;
因為這兩個情況的組合至多有 \(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 */