LINK:生成树



这场比赛我打的真失败 T3是比较容易的 却一直刚 那道"数论"

10分其实搜一下全排列。

30分容易想到对边进行装压dp。

不过存在一些细节 可以对于一个连通块的壮大进行装压 也就是每次需要联通两个块的时候使用关键边 然后再这两个块之间加边知道加满需要其他边。

复杂度 \(2^{21}\cdot 21\cdot 6\) 可能能过或许是我的做法不太行?

值得一提的是这样是无标号的需要最后乘以一个阶乘.

可以发现之所以装压边是为了防止 一些边的添加使得最小生成树变化。

可以考虑从小到大加边 是关键边就连接两个连通块 不是的话就添加到联通块的内部。

可以考虑对连通块进行装压 可以发现所以可能的情况只有3e5左右种.

那么就有\(f_{i,j}\)表示加到i条边连通块的情况为j的方案数.

将边从小到大排序就不需要考虑 且按照上述策略就一定不会改变最小生成树的形态.

当第i条边需要连接联通块的时候 可以在 状态中的两个联通块中选出两个连边就行辣 这部分复杂度 \(n^3\)不过很大程度上是跑不满的。

当需要连到联通块的内部的时候 那就预处理一下当前状态 能在连通块中加多少条边即可。转移的复杂度为O(1).

因为每个状态最多连边一次 所以

总复杂度\(n\cdot S+S\cdot n^3\)不过是跑不满的 n^3.

可以通过!

code
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 10000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-4
#define sq sqrt
#define S second
#define F first
#define mod 1000000007
#define V vector<int>
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=40010,maxn=40*40/2;
int f[maxn][MAXN];
V g[MAXN],now;
map<V,int>H;
int vis[maxn],w[MAXN];
int n,m,id;
inline void add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
inline int mul(int x,int y){return (ll)x*y%mod;}
inline void dfs(int x,int res)
{
if(!res)
{
H[now]=++id;g[id]=now;
vep(0,now.size(),j)w[id]+=(now[j]*(now[j]-1))/2;
return;
}
if(x>res)return;
now.pb(x);
dfs(x,res-x);
now.pop_back();
dfs(x+1,res);
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
get(n);m=n*(n-1)/2;
rep(1,n-1,i)vis[read()]=1;
dfs(1,n);
f[0][1]=1;
rep(1,m,i)
{
rep(1,id,j)if(f[i-1][j])
{
if(vis[i])
{
vep(0,g[j].size(),l)
vep(l+1,g[j].size(),r)
{
now.clear();
vep(0,g[j].size(),k)if(k!=l&&k!=r)now.pb(g[j][k]);
now.pb(g[j][l]+g[j][r]);
sort(now.begin(),now.end());
int ww=H[now],cc=mul(g[j][l],g[j][r]);
add(f[i][ww],mul(cc,f[i-1][j]));
}
}
else add(f[i][j],mul(f[i-1][j],w[j]-i+1));
}
}
put(f[m][id]);return 0;
}

最新文章

  1. iOS 保持界面流畅的技巧 (转载)
  2. (转)内置系统账户:Local system/Network service/Local Service 区别
  3. error C2039: &ldquo;bind2nd&rdquo;: 不是&ldquo;std&rdquo;的成员
  4. sql server 数据库备份,完整备份,差异备份,自动备份说明
  5. 添加 Windows 8.1 无虚拟机启动项 解决极品飞车的不支持虚拟机报错
  6. PHP mkdir 方法 创建 0777 权限的目录问题
  7. ILOG的一个基本应用——解决运输问题、转运问题
  8. Linkedlist,arrayDeque,HashMap,linkedHashMap
  9. gcc常用命令介绍
  10. hdu 4635 Strongly connected(Tarjan)
  11. Mysql Partition 理论知识总结
  12. php随机密码
  13. json编解码
  14. seajs + easyui [转]
  15. Linux学习 -- 文件系统管理
  16. 第三章 启动rabbitmq的webUI
  17. 弹性盒子模型属性之flex-shrink
  18. hdu 3499 flight 【分层图】+【Dijkstra】
  19. poj 1904(强连通分量+输入输出外挂)
  20. 【iCore1S 双核心板_FPGA】例程十四:FSMC总线通信实验——独立地址模式

热门文章

  1. css3中样式计算属性calc()的使用和总结
  2. MySQL索引 索引分类 最左前缀原则 覆盖索引 索引下推 联合索引顺序
  3. Face The Right Way思维。。。
  4. 阿里云服务器ecs配置之安装jdk(转)
  5. ASP.NET MVC Route详解
  6. day8 for循环+基本数据类型(上)
  7. 谈谈JVM(基础模型)
  8. 如何用HMS Nearby Service给自己的App添加近距离数据传输功能
  9. log4j系统日志(转载)
  10. 第一讲 Windows10系统下IDE-CLion的安装与配置