标签:continue char std bool ons getchar line back nts
对\(n(n\le10^5)\)个点,\(m(m\le n+5)\)条边的无向图进行黑白染色。要求相邻两个点不能都是黑色,问有多少染色方法。
将多出来的\(6\)条边进行容斥,强制这些边都是黑色。时间复杂度\(\mathcal O(6^2n)\)。
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
typedef long long int64;
const int N=1e5+1;
const int mod=1e9+7;
int n,m,f[2][N],cnt;
std::vector<int> e[N];
struct Edge {
int u,v;
};
Edge edge[6];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
int b[N];
void dfs(const int &x,const int &par) {
f[0][x]=b[x]!=1;
f[1][x]=b[x]!=0;
for(unsigned i=0;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par) continue;
dfs(y,x);
f[0][x]=(int64)f[0][x]*(f[0][y]+f[1][y])%mod;
f[1][x]=(int64)f[1][x]*f[0][y]%mod;
}
}
class DisjointSet {
private:
int anc[N];
int find(const int &x) {
return x==anc[x]?x:anc[x]=find(anc[x]);
}
public:
void reset() {
for(register int i=1;i<=n;i++) anc[i]=i;
}
void merge(const int &x,const int &y) {
anc[find(x)]=find(y);
}
bool same(const int &x,const int &y) {
return find(x)==find(y);
}
};
DisjointSet s;
int main() {
n=getint(),m=getint();
std::fill(&b[1],&b[n]+1,-1);
s.reset();
for(register int i=0;i<m;i++) {
const int u=getint(),v=getint();
if(s.same(u,v)) {
edge[cnt++]=(Edge){u,v};
} else {
add_edge(u,v);
s.merge(u,v);
}
}
int ans=0;
for(register int i=0;i<1<<cnt;i++) {
for(register int j=0;j<cnt;j++) {
if((i>>j)&1) b[edge[j].u]=b[edge[j].v]=1;
}
dfs(1,0);
ans+=((f[0][1]+f[1][1])%mod)*((__builtin_popcount(i)&1)?-1:1);
ans=(ans%mod+mod)%mod;
for(register int j=0;j<cnt;j++) {
if((i>>j)&1) b[edge[j].u]=b[edge[j].v]=-1;
}
}
printf("%d\n",ans);
return 0;
}
标签:continue char std bool ons getchar line back nts
原文地址:https://www.cnblogs.com/skylee03/p/9457193.html