练习赛44
Begin: 2019-04-03 18:35
PDD:355rlb
A
Kefa and Park CodeForces 580C
标签:暴力dfs(55)
题目大意:
? 一棵以1为根的树,树上有些点是红的。一个叶子是合法的当且仅当从根到它的路径上出现的连续红点个数不超过m。求有多少个叶子是合法的。
思路:
直接搜索就可以了,注意细节。
CODE:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
bool a[N];
vector<int>e[N];
int ans,n,m;
void dfs(int x,int d,int fa){
for(int i=0;i<e[x].size();i++){
int y=e[x][i];
if(y==fa)continue;
if(!a[y]){
if(e[y].size()==1)ans++;
dfs(y,0,x);
}
else if(d<m){
if(e[y].size()==1)ans++;
dfs(y,d+a[y],x);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
e[u].push_back(v),e[v].push_back(u);
}
dfs(1,a[1],0);
printf("%d",ans);
}
B
Kefa and Dishes CodeForces - 580D
标签:状压dp(75)
题目大意:
? kefa进入了一家餐厅,这家餐厅中有n个菜(0<n≤18),kefa对第i个菜的满意度为ai(0≤ai≤10^9),并且对于这n个菜有k个规则,如果kefa在吃完第xi个菜之后吃了第yi个菜(保证xi、yi不相等),那么会额外获得ci(0≤ci≤10^9)的满意度。kefa要吃m道任意的菜(0<m≤n),但是他希望自己吃菜的顺序得到的满意度最大,请你帮帮kefa吧!
思路:
基本操作都一样,dp包括两维:已经吃过的菜,刚刚吃过的菜。还有就是注意long long
CODE:
#include<bits/stdc++.h>
using namespace std;
const int N=20;
long long t[25][25],a[25],dp[1<<N][25];
long long ans;
int calc(int x){
int res=0;
for(int i=0;i<=19;i++){
if(x&(1<<i))res++;
}
return res;
}
int main(){
int n,m,k;
memset(dp,-1,sizeof(dp));
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
dp[1<<i][i]=a[i];
}
for(int i=1,u,v;i<=k;i++){
long long d;
scanf("%d%d%lld",&u,&v,&d);u--,v--;
t[u][v]=d;
}
for(int i=0;i<(1<<n);i++){
int cnt=calc(i);
bool ok=0;
if(cnt==m)ok=1;
for(int j=0;j<n;j++){
if(dp[i][j]==-1)continue;
if(ok)ans=max(ans,dp[i][j]);
for(int o=0;o<n;o++){
int stu=1<<o;
if(i&stu)continue;
dp[i|stu][o]=max(dp[i|stu][o],dp[i][j]+t[j][o]+a[o]);
}
}
}
printf("%lld",ans);
}
C
A and B and Lecture Rooms CodeForces - 519E
标签:YY+LCA(90)
题目大意:
在大学里,小A和小B是一对非常要好的朋友,他们经常一起参加比赛。现在,这个大学里有n个教室,这n个教室用n-1个走廊相互连接,因此学生可以从一个教室经过走廊走到任何其他的教室。 每天,小A和小B都要讨论一些问题。每次下课以后(小A和小B在不同的地方上课),小A和小B就相约去同一个教室讨论问题。小A和小B希望讨论的教室离他们现在各自所在的教室距离相等。两个教室之间的距离指的是他们的最短距离。由于小A和小B每天都要讨论问题,所以他们希望你能帮助他们计算出在接下来的m天里,离他们各自所在的位置距离相等的教室有多少个。
思路:
如果直接暴力枚举每个节点肯定会T。所以得y y一下。设u,v的LCA为lca,则dis(u,v)=dep(u)+dep(v)-2dep(lca)
Case1:u==v则答案为n
Case2: 如果dis(u,v)为偶,则一定不存在某点到 u,v 的距离相等;
Case3:如果dis(u,v)为奇,且dep[u]==dep[v],则路径上的中点就是lca;
Case4:如果dis(u,v)为奇,且dep[u]==dep[v],则路径上的中点在深度较大的那一侧上;
具体看代码,这里求lca用了树剖,其实用倍增会更简洁。
CODE:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;
int f[N][20],sz[N],dep[N],son[N],top[N];
vector<int>e[N];
int UP(int x,int p){
for(int i=0;i<=17;i++)
if(p&(1<<i))x=f[x][i];
return x;
}
int main(){
n=read();
for(int i=1,u,v;i<n;i++){
u=read(),v=read();
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1);
dfs2(1,1);
for(int i=1;i<=17;i++)
for(int j=1;j<=n;j++)f[j][i]=f[f[j][i-1]][i-1];
m=read();
for(int i=1,u,v;i<=m;i++){
u=read(),v=read();
if(u==v){printf("%d\n",n);continue;}
if(dep[u]<dep[v])swap(u,v);
int lca=LCA(u,v),dis=dep[u]+dep[v]-2*dep[lca]-1;
if(dis&1){
if(dep[u]==dep[v]){//case3
u=UP(u,dis/2);v=UP(v,dis/2);
printf("%d\n",n-sz[u]-sz[v]);
}
else{//case4
u=UP(u,dis/2);
int now=f[u][0];
printf("%d\n",sz[now]-sz[u]);
}
}
else puts("0");
}
}
D
Tree CodeForces - 23E
略uus
原文地址:https://www.cnblogs.com/Tieechal/p/11189375.html