您的位置:首页 > 其它

bzoj4596 [Shoi2016]黑暗前的幻想乡

2018-01-03 21:52 309 查看
如果要用矩阵树的话是无法限制公司个数的,发现数据范围十分小,于是考虑容斥,最后答案就等于$n-1$个公司的方案数-$n-2$个公司的方案数+$n-3$个公司的方案数$...$,然后跑矩阵树就好了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#define N 20
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define int long long
using namespace std;
int a

,n;
int gauss(){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
(a[i][j]+=mod)%=mod;
/*for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
printf("%lld ",a[i][j]);
puts("");
}puts("");*/
int ans=1;
for(int k=1;k<n;k++){
for(int i=k+1;i<n;i++){
while(a[i][k]){
int t=a[k][k]/a[i][k];
for(int j=k;j<n;j++){
a[k][j]=(a[k][j]-t*a[i][j]%mod+mod)%mod;
swap(a[k][j],a[i][j]);
}
ans=(-ans+mod)%mod;
}
}
ans=(ans*a[k][k])%mod;
}
//printf("%lld\n",ans);
return ans;
}
void add(int x,int y){
a[x][x]++;a[y][y]++;
a[x][y]--;a[y][x]--;
}
vector<pair<int,int> >v
;
int bit[20];
int getnum(int x){
int cnt=0;
while(x){cnt++;x^=x&-x;}
return cnt;
}
signed main(){
bit[0]=1;
for(int i=1;i<=17;i++)bit[i]=bit[i-1]<<1;
scanf("%lld",&n);
for(int i=1,num;i<n;i++){
scanf("%lld",&num);
for(int j=1,x,y;j<=num;j++){
scanf("%lld%lld",&x,&y);
v[i].pb(mp(x,y));
}
}
int tot=0;
for(int i=0;i<bit[n-1];i++){
memset(a,0,sizeof a);
for(int j=1;j<=n;j++)if(i&bit[j-1]){
for(int k=0,x,y;k<v[j].size();k++){
x=v[j][k].first,y=v[j][k].second;
add(x,y);
}
}
int now=gauss();
if((getnum(i)&1)^((n-1)&1))tot=(tot-now+mod)%mod;
else tot=(tot+now)%mod;
}
printf("%lld\n",tot);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: