【清华集训2014】【BZOJ3812】主旋律
2016-04-03 14:28
267 查看
Description
响应主旋律的号召,大家决定让这个班级充满爱,现在班级里面有 n 个男生。
如果 a 爱着 b,那么就相当于 a 和 b 之间有一条 a→b 的有向边。如果这 n 个点的图是强联通的,那么就认为这个班级是充满爱的。
不幸的是,有一些不好的事情发生了,现在每一条边都可能被摧毁。我作为爱的使者,想知道有多少种摧毁的方式,使得这个班级任然充满爱呢?(说人话就是有多少边的子集删去之后整个图仍然强联通。)
Input
第一行两个数 n 和 m,表示班级里的男生数和爱的关系数。
接下来 m 行,每行两个数 a 和 b,表示男生 a 爱着男生 b。同时 a 不等于 b。
所有男生从 1 到 n 标号。
同一条边不会出现两遍,但可能出现 a 爱着 b,b 也爱着 a 的情况,这是两条不同的边。
Output
输出一行一个整数,表示对 109+7 取模后的答案。
Sample Input
5 15
4 3
4 2
2 5
2 1
1 2
5 1
3 2
4 1
1 4
5 4
3 4
5 3
2 3
1 5
3 1
Sample Output
9390
HINT
对于 100% 的数据满足: n≤15,0≤m≤n(n−1)。
Source
2015年国家集训队测试
一道很传统的题目.
首先很容易想到是状压DP.
题目所求的东西,可以转化为一个问题:”原图有多少个子图是强连通的.”
这个问题本身不太好做,但是我们可以考虑从他的对立面”多少子图是不强连通的”入手.
显然如果一个子图是不强连通的,那么他缩点后一定是一个节点数目大于等于2的DAG.
所以可以用总方案数减掉能划分出缩点后节点数目大于等于2的方案数,只要枚举有多少点点集缩点后是一个DAG,然后DP就行了.
既然选取的点集缩点后一定是个DAG,那么接下来的问题就变成了:给定一张有向图,有多少种选边方案使得选出来的子图构成一个DAG.
那么我们考虑枚举一个点集V,枚举出度为0的点集V’.然后可以容斥+DP.容斥过程中可以发现,如果V’中选的点缩完是奇数个点,对答案贡献是正的,否则是负的.然后只要算出奇数个点的方案减去偶数个点的方案就行了.
然而到这里还是只能在原题得70分…最后还要预处理一个 点集划分成奇数个没有出度的点减去偶数个没有出度的点 的方案数.
我的题解可能比较碎而且看不懂..可以看Po姐的代码里的注释,更加直接..
响应主旋律的号召,大家决定让这个班级充满爱,现在班级里面有 n 个男生。
如果 a 爱着 b,那么就相当于 a 和 b 之间有一条 a→b 的有向边。如果这 n 个点的图是强联通的,那么就认为这个班级是充满爱的。
不幸的是,有一些不好的事情发生了,现在每一条边都可能被摧毁。我作为爱的使者,想知道有多少种摧毁的方式,使得这个班级任然充满爱呢?(说人话就是有多少边的子集删去之后整个图仍然强联通。)
Input
第一行两个数 n 和 m,表示班级里的男生数和爱的关系数。
接下来 m 行,每行两个数 a 和 b,表示男生 a 爱着男生 b。同时 a 不等于 b。
所有男生从 1 到 n 标号。
同一条边不会出现两遍,但可能出现 a 爱着 b,b 也爱着 a 的情况,这是两条不同的边。
Output
输出一行一个整数,表示对 109+7 取模后的答案。
Sample Input
5 15
4 3
4 2
2 5
2 1
1 2
5 1
3 2
4 1
1 4
5 4
3 4
5 3
2 3
1 5
3 1
Sample Output
9390
HINT
对于 100% 的数据满足: n≤15,0≤m≤n(n−1)。
Source
2015年国家集训队测试
一道很传统的题目.
首先很容易想到是状压DP.
题目所求的东西,可以转化为一个问题:”原图有多少个子图是强连通的.”
这个问题本身不太好做,但是我们可以考虑从他的对立面”多少子图是不强连通的”入手.
显然如果一个子图是不强连通的,那么他缩点后一定是一个节点数目大于等于2的DAG.
所以可以用总方案数减掉能划分出缩点后节点数目大于等于2的方案数,只要枚举有多少点点集缩点后是一个DAG,然后DP就行了.
既然选取的点集缩点后一定是个DAG,那么接下来的问题就变成了:给定一张有向图,有多少种选边方案使得选出来的子图构成一个DAG.
那么我们考虑枚举一个点集V,枚举出度为0的点集V’.然后可以容斥+DP.容斥过程中可以发现,如果V’中选的点缩完是奇数个点,对答案贡献是正的,否则是负的.然后只要算出奇数个点的方案减去偶数个点的方案就行了.
然而到这里还是只能在原题得70分…最后还要预处理一个 点集划分成奇数个没有出度的点减去偶数个没有出度的点 的方案数.
我的题解可能比较碎而且看不懂..可以看Po姐的代码里的注释,更加直接..
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define P 1000000007 #define MAXN 16 #define GET (ch>='0'&&ch<='9') using namespace std; int n,m; int bit[1<<MAXN],use[1<<MAXN],tmp[1<<MAXN]; int f[1<<MAXN],g[1<<MAXN],h[1<<MAXN]; int In[MAXN],Out[MAXN]; int Pow[MAXN*MAXN]; inline void in(int &x) { char ch=getchar();x=0; while (!GET) ch=getchar(); while (GET) x=x*10+ch-'0',ch=getchar(); } int main() { in(n);in(m);Pow[0]=1;int u,v; for (int i=1;i<=n*n;i++) Pow[i]=(Pow[i-1]<<1)%P; for (int i=1;i<(1<<n);i++) bit[i]=bit[i-(i&-i)]+1; for (int i=1;i<(1<<n);i++) for (int j=0;j<n;j++) if (i&(1<<j)) use[i]=j; for (int i=1;i<=m;i++) in(u),in(v),u--,v--,Out[u]|=1<<v,In[v]|=1<<u; f[0]=1;g[0]=P-1;h[0]=1; for (int i=1;i<(1<<n);i++) { if (bit[i]==1) { f[i]=g[i]=h[i]=1;continue; } int sum=0;//edge number for (int j=0;j<n;j++) if (i&(1<<j)) sum+=bit[Out[j]&i]; h[i]=f[i]=Pow[sum];g[i]=0; int x=use[i],V=i-(1<<x);//choose a node named x, other nodes named set V for (int j=V;;(--j)&=V) { int now=j|(1<<x); if (now<i) ((g[i]-=1ll*f[now]*g[i-now]%P)+=P)%=P; if (j==0) break; } int Sum=0; for (int j=i;j;(--j)&=i) { if (j==i) tmp[j]=0; else { int x=use[i-j],now=j|(1<<x); tmp[j]=tmp[now]-bit[Out[x]&(i-now)]+bit[In[x]&j]; } int edgecnt=tmp[j],t=1ll*g[j]*h[i-j]%P*Pow[edgecnt]%P; (Sum+=t)%=P; } ((f[i]-=Sum)+=P)%=P;(g[i]+=f[i])%=P; } cout<<f[(1<<n)-1]<<endl; }
相关文章推荐
- hdu1827&&hdu2767----Kosaraju算法
- hdu3072&&hdu3639----Kosaraju算法
- Codeforces Round #198 (Div. 1)
- 4495: Least Prime factor 找到最小质因子P的第N小正整数
- POJ 3254 - Corn Fields [状压DP]
- hdu5072 Coprime 2014鞍山现场赛C题 容斥原理+单色三角
- poj 2836
- poj 3254
- POJ 2441
- 2014 西安邀请赛状压DP
- Mega Man’s Missions
- [BZOJ1797][AHOI2009][最大流][强连通分量]Mincut最小割
- [BZOJ2330][SCOI2011][拓扑排序][强连通分量][Tarjan]Candy
- 二维树状数组
- MZ Training 2014 #4 C题
- 图论算法(6) --- Tarjan算法求强连通分量
- 图论算法(6)(更新版) --- Tarjan算法求强连通分量
- POJ2186
- HDU 1695 GCD
- POJ3114 Country in Wars Tarjan+Dij