Description

Input

Output

Sample Input
7 7
3 1
2 1
7 6
6 3
5 3
4 3
7 2 3
7 1 1
2 3 5
3 6 2
4 2 4
5 3 10
6 1 20
3
5
6
7
Sample Output
10
22
5
Data Constraint

Hint

赛时
考虑一个部分分的dp,然后空间竟然爆掉了!!!
结果40分
正解(呸 )
一坨大佬暴力解决???加个小小剪枝?(if(当前答案>ans)return)
然后水题开始
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 100007
using namespace std;
int n,m,fa[N],w[N][100],k[N][100],num[N],q,ans;
void dfs(int x,int y,int z){
if(z>ans) return;//小小优化,从40怒怼100分
if(x==1){
ans=min(ans,z);//记录答案
return;
}
if(y!=0) dfs(fa[x],y-1,z);
for(int i=1;i<=num[x];i++){
dfs(fa[x],k[x][i]-1,z+w[x][i]);//选择买票
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);//题目说单向联通,所以直接确定父亲了
fa[u]=v;
}
for(int i=1;i<=m;i++){
int u,v,o;
scanf("%d%d%d",&u,&v,&o);
k[u][++num[u]]=v;
w[u][num[u]]=o;//邻接表来记录每个点的票的次数以及值
}
scanf("%d",&q);
while(q--){
int x;
scanf("%d",&x);
ans=0x3f3f3f3f;
dfs(x,0,0);//第一个参是目前节点,第二个是目前剩的票,第三个是答案
printf("%d\n",ans);
}
}
十万大数据就被这么过了?(暴力出奇迹,n方过百万 )
真-正解(只是想水分的同志请自行跳过)
设f[i]表示当前i节点的答案,它=min{f[j]+k},j是i的祖先,显然这个是成立的,然后至于j的取值范围就跟i的深度比下就行了,要小于k。之后维护j的最小值(熟练剖分它不香吗 )建议打倍增就行了。
代码:
代码?你还想要代码?水分它不香?反正我没码
285



被折叠的 条评论
为什么被折叠?



