您的位置:首页 > 其它

BZOJ 4596: [Shoi2016]黑暗前的幻想乡

2016-05-26 21:11 375 查看
迷之正确性的做法

首先观察数据范围,哎和ZJOI的小星星一毛一样啊,会不会给人一种钦定复杂度的感觉啊

于是就乱搞一发,容斥+Matrix Tree定理

莫名其妙地就过了QAQ

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<ctime>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
#define mk(x,y) make_pair(x,y)
const int N=20;
const int p=(1e9)+7;
ll g

;
int n;
void print(){
rep(i,1,n){
rep(j,1,n)printf("%lld ",g[i][j]);
puts("");
}
}
ll iabs(ll x){return x<0?-x:x;}
ll Gauss(){
ll ans=1;
rep(i,1,n-1){
rep(j,i+1,n-1)
while(g[j][i]){
ll t=g[i][i]/g[j][i];
rep(k,i,n-1)
g[i][k]=(g[i][k]-g[j][k]*t)%p;
rep(k,i,n-1)
swap(g[i][k],g[j][k]);
ans=-ans;
}
ans=ans*g[i][i]%p;
if(!ans)return 0;
}
return (ans+p)%p;
}
vector<pr >pl
;
int main(){
scanf("%d",&n);
rep(i,1,n-1){
int m;scanf("%d",&m);
while(m--){int u,v;scanf("%d%d",&u,&v);pl[i].push_back(mk(u,v));}
}
ll ans=0;
per(i,(1<<(n-1))-1,0){
int cnt=0;
mmt(g,0);
rep(j,1,n-1)
if(i>>(j-1)&1){
per(k,(int)pl[j].size()-1,0){
int u=pl[j][k].first,v=pl[j][k].second;
g[u][u]++;g[v][v]++;
g[u][v]--;g[v][u]--;
}
cnt++;
}
if((n-cnt)&1)ans=(ans+Gauss())%p;
else ans=(ans-Gauss())%p;
}
printf("%lld\n",(ans+p)%p);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: