您的位置:首页 > 其它

2016长乐夏令营 Day13

2016-07-27 23:22 232 查看
T1:

如果x >= y 那么答案显然(n-1)*y 不过要特判菊花图

如果x < y,问题就变成在一棵树上尽可能多的选择链

f[i][k]代表以i为根的子树,i连边的状态为k,选的最多的边的数量

k <= 2

转移显然#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<bitset>
using namespace std;

typedef long long LL;
const int maxn = 1E6 + 10;
const int INF = 1E9;

int n,du[maxn];
LL x,y,ans,f[maxn][3];

vector <int> v[maxn];

int dfs(int x,int fa)
{
f[x][0] = f[x][1] = f[x][2] = 0;
int x1,x2,res,r,son;
x1 = x2 = -INF; son = 0;
for (int i = 0; i < v[x].size(); i++) {
int to = v[x][i];
if (to == fa) continue;
++son;
f[x][0] += (r = dfs(to,x));
res = max(f[to][0],f[to][1]) - r;
if (res >= x1) {
x2 = x1;
x1 = res;
}
else if (res > x2) x2 = res;
}
if (son > 0) f[x][1] = max(f[x][0] + x1,0LL) + 1;
if (son > 1) f[x][2] = max(f[x][0] + x1 + x2,0LL) + 2;
return max(f[x][0],max(f[x][1],f[x][2]));
}

int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#else
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
#endif

cin >> n >> x >> y;
for (int i = 1; i < n; i++) {
int a,b; scanf("%d%d",&a,&b);
v[a].push_back(b);
v.push_back(a);
++du[a]; ++du[b];
}
if (x >= y) {
ans = 1LL*(n-1)*y;
bool flag = 0;
for (int i = 1; i <= n; i++)
if (du[i] == n - 1) flag = 1;
if (flag) ans += (x - y);
cout << ans;
}
else {
int Max = dfs(1,0);
ans = 1LL*Max*x + 1LL*(n - 1 - Max)*y;
cout << ans;
}
return 0;
}



[b]T2: 待填




T3:

f[i]:状态为i的点构成的合法树的个数

g[i]:状态为i的构成的合法森林的个



f[i] = ∑g[o-做根的节点]

森林:森林+一棵新树

g[i] = ∑f[op]*g[o-op]  op一定是含o最左边数位的节点


初值:g[0] = 1



一开始以为L、R是儿子数。。傻逼了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<bitset>
using namespace std;

typedef long long LL;
const int maxn = 20;
const int maxm = 1<<15;
const LL mo = 1E9 + 7;

int n,L[maxn],R[maxn];
LL f[maxm],g[maxm];

int cal(int o)
{
int ret = 0;
for (; o; o >>= 1)
if (o & 1) ++ ret;
return ret;
}

int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#else
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
#endif

cin >> n;
for (int i = 1; i <= n; i++) scanf("%d%d",&L[i],&R[i]);
g[0] = 1;
for (int o = 1; o < (1<<n); o++) {
int siz = cal(o),pos;
for (int i = 1; i <= n; i++) {
if (!(o&(1<<(i-1)))) continue;
pos = i;
if (siz < L[i] || R[i] < siz) continue;
f[o] = (f[o] + g[o - (1<<(i-1))]) % mo;
}
--pos;
int opt = o - (1<<pos);
if (siz > 1) g[o] = f[o];
for (int op = (opt - 1) & opt; op; op = (op - 1) & opt)
g[o] = (g[o] + f[(1<<pos) + op]*g[opt - op] % mo) % mo;
g[o] = (g[o] + f[1<<pos]*g[opt]%mo) % mo;
}
cout << f[(1<<n) - 1];
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: