HDU 4123 (2011 Asia FZU contest)(树形DP + 维护最长子序列)(bfs + 尺取法)
题意:告诉一张带权图,不存在环,存下每个点能够到的最大的距离,就是一个长度为n的序列,然后求出最大值-最小值不大于Q的最长子序列的长度。
做法1:两步,第一步是根据图计算出这个序列,大姐头用了树形DP(并不懂DP),然后就是求子序列长度,其实完全可以用RMQ爆,但是大姐头觉得会超时,于是就采用维护最大,最小值(差超过Q的时候就删掉,然后记录长度)。
做法2:通过3次bfs求树的直径(为什么啊),然后RMQ求出所有区间的最大最小值
时间复杂度:290ms
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
#define ll long long
#define _cle(m, a) memset(m, a, sizeof(m))
#define repu(i, a, b) for(int i = a; i < b; i++)
#define repd(i, a, b) for(int i = b; i >= a; i--)
#define sfi(n) scanf("%d", &n)
#define sfl(n) scanf("%I64d", &n)
#define pfi(n) printf("%d\n", n)
#define pffi(n, m) printf("%d %d\n", n, m)
#define pfl(n) printf("%I64d\n", n)
#define MAXN 50005
int n, m;
int d[MAXN][], cd[MAXN], dp[MAXN];
bool vis[MAXN];
struct P
{
int y, w;
P(int _x = , int _w = ) : y(_x), w(_w) {}
};
vector<P> v[MAXN];
int p[MAXN];
int num[MAXN];
void dfs(int root)
{
if(vis[root]) return ;
vis[root] = ;
int siz = v[root].size();
repu(i, , siz) dfs(v[root][i].y);
int maxn = ;
repu(i, , siz)
if(maxn < d[v[root][i].y][] + v[root][i].w)
{
maxn = d[v[root][i].y][] + v[root][i].w;
cd[root] = v[root][i].y;
}
d[root][] = maxn;
int c = ;
repu(i, , siz)
if(c < d[v[root][i].y][] + v[root][i].w && v[root][i].y != cd[root])
c = d[v[root][i].y][] + v[root][i].w;
d[root][] = c;
}
void DP(int root)
{
if(vis[root]) return ;
vis[root] = ;
int siz = v[root].size();
repu(i, , siz) if(!vis[v[root][i].y])
{
if(cd[root] != v[root][i].y)
dp[v[root][i].y] = max(d[root][], dp[root]) + v[root][i].w;
else
dp[v[root][i].y] = max(d[root][], dp[root]) + v[root][i].w;
DP(v[root][i].y);
}
return ;
}
int main()
{
while(sfi(n), sfi(m), (n + m))
{
memset(d,,sizeof(d));
memset(dp,,sizeof(dp));
memset(vis,,sizeof(vis));
memset(cd,,sizeof(cd));
repu(i, , n + ) v[i].clear();
int x, y, w;
repu(i, , n - )
{
sfi(x), sfi(y), sfi(w);
v[x].push_back(P(y, w));
}
vector<P>::iterator it;
dfs();
repu(i, , n + )
if(!vis[i])
{
int siz = v[i].size();
if(!siz) continue;
int flag = ;
it = v[i].begin();
for(; it != v[i].end(); it++)
{
if(vis[it -> y])
{
flag = ;
break;
}
}
v[it -> y].push_back(P(i, it -> w));
v[i].erase(it);
dfs(i);
}
memset(d,,sizeof(d));
memset(dp,,sizeof(dp));
memset(vis,,sizeof(vis));
memset(cd,,sizeof(cd));
repu(i, , n + )
if(!vis[i]) dfs(i); memset(vis,,sizeof(vis));
repu(i, , n + )
if(!vis[i]) DP(i); repu(i, , n + )
p[i] = max(d[i][], dp[i]); int Q;
repu(i, , m)
{
scanf("%d", &Q);
int maxnum = ;
int num = ;
int last = ;
int maxn = p[];
int minn = p[];
int maxp = ;
int minp = ;
repu(j, , n + )
{
if(p[j] > maxn)
{
if(p[j] - minn > Q)
{
maxnum = max(maxnum, num);
num = ;
j = min(minp + , maxp + );
maxn = p[j];
minn = p[j];
maxp = j;
minp = j;
}
else
{
num++;
maxn = p[j];
maxp = j;
}
}
else if(p[j] < minn)
{
if(maxn - p[j] > Q)
{
maxnum = max(maxnum, num);
num = ;
j = min(minp + , maxp + );
maxn = p[j];
minn = p[j];
maxp = j;
minp = j;
}
else
{
num++;
minn = p[j];
minp = j;
}
}
else
num++;
}
maxnum = max(maxnum, num);
pfi(maxnum);
}
}
return ;
}
树形DP+单调队列--大姐头
时间复杂度:936ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define ALL(a) a.begin(), a.end()
#define clr(a, x) memset(a, x, sizeof a)
#define fst first
#define snd second
#define pb push_back
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> pil;
#define maxn 50050
int n, m, du[maxn];
int d[maxn];
vector<pil> G[maxn];
struct RMQ
{
int Dp[maxn][];
int mm[maxn];
void init(int n,int b[])
{
mm[] = -;
for(int i = ; i <= n; i++)
{
mm[i] = ((i&(i-)) == )?mm[i-]+:mm[i-];
Dp[i][] = b[i];
}
for(int j = ; j <= mm[n]; j++)
for(int i = ; i + (<<j) - <= n; i++)
Dp[i][j] = max(Dp[i][j-],Dp[i+(<<(j-))][j-]);
}
int rmq(int x,int y)
{
int k = mm[y-x+];
return max(Dp[x][k],Dp[y-(<<k)+][k]);
}
} Min,Max;
int dis[maxn]= {};
bool vis[maxn]= {};
queue<int> q; int bfs(int u)
{
clr(dis, );
clr(vis, );
int ans=, Max=;
q.push(u);
dis[u]=, vis[u]=;
while(!q.empty())
{
int u=q.front();
q.pop();
if(dis[u]>Max)
Max=dis[ans=u];
for(int i=; i<G[u].size(); i++)
{
pil t=G[u][i];
int v=t.fst, w=t.snd;
if(vis[v])continue ;
dis[v]=dis[u]+w;
vis[v]=true;
q.push(v);
}
}
for(int i=; i<=n; i++)
d[i]=max(d[i], dis[i]);
return ans;
} int main()
{
while(~scanf("%d%d", &n, &m) && n+m)
{
for(int i=; i<=n; i++)
{
G[i].clear();
d[i]=;
}
for(int i=; i<n-; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u].pb(mp(v, w));
G[v].pb(mp(u, w));
}
///每次bfs都是求出所有点到起点的距离(只有一条路,没有最大最小)
///然后返回与起点距离最大的点MAX,再求一次所有点与MAX距离最大的点。
///求3次就可以把每个点的最大距离求出来
bfs(bfs(bfs()));
Max.init(n, d);
///从最大值到最小值换成相反数即可
for(int i=; i<=n; i++)
d[i]=-d[i];
Min.init(n, d);
while(m--)
{
int q, ans=;
scanf("%d", &q);
int ok = ;
for(int i=, j=; i<=n; i++)
{
///原来是尺取法,傻傻的我以为完全暴力
///j只是从1开始,然后只是增加,一直到等于n
while(j<=n && Max.rmq(i, j)+Min.rmq(i, j)<=q)
ans=max(ans, j-i+), j++;
}
printf("%d\n", ans);
}
}
return ;
}
3次bfs + 尺取法----SX神
HDU 4123 (2011 Asia FZU contest)(树形DP + 维护最长子序列)(bfs + 尺取法)的更多相关文章
- HDU 4123 Bob’s Race(树形DP,rmq)
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 1520.Anniversary party 基础的树形dp
Anniversary party Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- HDU 1054 Strategic Game(最小点覆盖+树形dp)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106048#problem/B 题意:给出一些点相连,找出最小的点数覆盖所有的 ...
- HDU 3586 Information Disturbing(二分+树形dp)
http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意: 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超 ...
- HDU 5682 zxa and leaf 二分 树形dp
zxa and leaf 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5682 Description zxa have an unrooted t ...
- HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...
- HDU 6201 transaction transaction transaction(树形DP)
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...
- TTTTTTTTTTT hdu 1520 Anniversary party 生日party 树形dp第一题
Anniversary party Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- hdu 4612 Warm up 双连通+树形dp思想
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total S ...
随机推荐
- 浙江理工2015.12校赛-B 七龙珠
七龙珠 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 781 Solved: 329 Description 话说孙壕请吃了青岛大虾后,一下子变穷了,就 ...
- mysql之常用操作
1. 数据库介绍 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据.我们也可以将数 ...
- 计算城市间的球面距离(C++实现)
#include<iostream> #include<string> #include<cmath> #include<iomanip> using ...
- 微信小程序注册app
App() App() 函数用来注册一个小程序.接受一个 object 参数,其指定小程序的生命周期函数等. object参数说明 onLaunch Function 生命周期函数--监听小程序初 ...
- Scrum Meeting 3-20151203
任务安排 姓名 今日任务 明日任务 困难 董元财 请假(明天是编译截至最后一天) 学习上拉加入新的listview 无 胡亚坤 请假(明天是编译截至最后一天) 设计优化聊天页面 无 刘猛 请假(明天是 ...
- Android显示基础--单位与尺寸
px:是像素的意思,屏幕可以显示的最小元素单位,单独一个像素点非常小,肉眼都无法看到. pt:是磅数的意思,1磅等于七十二分之一英寸,pt一般用作字体的单位. dp:密度无关像素的意思,也被称为dip ...
- Skyfree的毕业论文 《系统封装与部署的深入研究》
Skyfree的毕业论文 <系统封装与部署的深入研究> https://www.itsk.com/thread-197-1-4.html Skyfree 发表于 2007-9-13 07: ...
- Android驱动之JNI编写
要想用java去调用C函数接口那么就需要使用JNI(Java Native Interface,Java 本地调用)去访问本地的动态链接库. 关于NDK的安装,现在有linux环境下的版本,也有win ...
- js——单选框radio
页面: ... <tr align="right"> <td align="right">会员性别:</td> <td ...
- CentOS7下安装FTP服务
1.安装vsftp 1.1.安装vsftp,测试安装的vsftpd的版本是:vsftpd.x86_64 0:3.0.2-11.el7_2 yum -y install vsftpd 1.2.修改配置文 ...