NOIP模拟四
摘要:全是想象学竞赛
T1
充满想象的题目,状压把每个人的参赛情况(0101这样的)压缩成 中的一个整数表示,再按照每个数的popcount从大到小贪心来凑,珂以按如下的组合凑:
code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=114514,M=1919810;
ll n,m,V,k,x;
ll a[N],sum[N];
bool cmp(ll x,ll y){return x>y;}
int main(){
//freopen("T1.in","r",stdin);
//freopen("T1.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m; V=(1<<m)-1;
for(int i=1;i<=m;++i){
cin>>k;
for(int j=1;j<=k;++j)
cin>>x,a[x]|=(1<<i-1);
}
sort(a+1,a+n+1);
sum[0]=1145141919810;
for(int i=n;i>=1;--i)
for(int j=V;j>=0;--j)
if(sum[j]&&!(j&a[i])){
--sum[j];
++sum[j|a[i]];
break;
}
ll ans=0;
for(int i=1;i<=V;++i) ans+=sum[i];
cout<<ans;
return 0;
}
T2
看出来时换根dp,没写出来, 分暴力滚粗。换根应该这么搞:
-
以 为根的子树中,选择一个包含 的连通块,使得每个点度数 (特别地, 的度数要 )的最大边权和;
-
整棵树去掉以 为根的子树后,选择一个包含 的父亲 的连通块,使得每个点度数 (特别地, 的度数要 )的最大边权和。
换根dp搞就是了,就是考的时候不会推不会写/kel,还有记得特判 ,有个老哥就是没有判零然后被subtask从100pts坑成0pts,
所以subtask能不能滚出OI赛制啊
code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2*1145140,M=1919810;
struct xx{
ll next,to,val;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y,ll z){
e[++cnt].next=head[x];
e[cnt].to=y;
e[cnt].val=z;
head[x]=cnt;
}
ll n,k,dp[N];
ll du[N],total,ans;
bool cmp(ll x,ll y){
return x>y;
}
void dfs_pre(ll u,ll fa){
vector <ll> g;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to,w=e[i].val;
if(v==fa) continue;
dfs_pre(v,u);
g.push_back(dp[v]+w);
}
sort(g.begin(),g.end(),cmp);
for(int i=0;i<min(k-1,(ll)g.size());++i)
dp[u]+=g[i];
}
void dfs_dp(ll u,ll fa,ll last){
//cout<<last<<'\n';
vector <ll> g;
g.push_back(last);
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to,w=e[i].val;
if(v==fa) continue;
g.push_back(dp[v]+w);
}
sort(g.begin(),g.end(),cmp);
ll sum=0,val=0;
for(ll i:g) sum+=i; //不开longlong见祖宗
ans=max(ans,sum); sum=0;
for(int i=0;i<min(k-1,(ll)g.size());++i)
sum+=g[i];
if(g.size()>=k) val=g[k-1];
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to,w=e[i].val,x=dp[v]+w;
if(v==fa) continue;
dfs_dp(v,u,(x>val?sum-x+val:sum)+w);
}
}
int main(){
//freopen("T1.in","r",stdin);
//freopen("T1.out","w",stdout);
//ios::sync_with_stdio(0);
//cin.tie(0); cout.tie(0);
cin>>n>>k; ll maxn=0;
for(int i=1;i<n;++i){
ll a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
total+=c; maxn=max(maxn,c);
}
if(k==0){
cout<<0;
return 0;
}
dfs_pre(1,0);
dfs_dp(1,0,0);
cout<<ans;
return 0;
}
T3&T4不想搞了,反正也不懂,抄题解吧
頑張って