山东财经大学新生赛暨天梯赛选拔赛-D E 线性dp/dfs
D-流星雨
题意描述
给定n个时间段l,r,首尾相接的时间段可以看成一段,求出最长的连续且不重叠的时间段。
题意分析
1.可以用一维状态表示以
i为结尾的最长的时间段的长度
2.状态转移方程
细节问题
- 注意在dp前要先预排序,将
l小的排在前面。
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+100;
struct node
{
int l,r;
}q[N];
int f[N],ans;
bool cmp(struct node a,struct node b)
{
if(a.l==b.l) return a.r<b.r;
return a.l<b.l;
}
int main()
{
int n;cin>>n;
for(int i=0;i<n;i++)
{
cin>>q[i].l>>q[i].r;
}
sort(q,q+n,cmp);
for(int i=0;i<n;i++)
{
int r=q[i].r,l=q[i].l;
f[r]=max(f[r],f[l]+r-l);
ans=max(ans,f[r]);
}
cout<<ans;
}
赛时没有做出来,我可能是脑子有点大病
E-旅行家
题意描述
给定N个点N-1条边的树,问从1节点走遍树上所有节点需要的最短距离
题意分析

如图,从1节点开始走遍整棵树,图中红色为只需要走一遍的路径,橙色为需要走两遍的路径。
如何使总距离最短?
答案:使只需要走一遍的距离最长
类似树的直径,但指定了直径的一端,故只需要对1dfs一遍找到最长直径,再用总路径*2减去最长直径即可得解
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+1000,M=N*2;
int h[N],e[M],w[M],ne[M],idx;
bool st[N];
int sum,ans;
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void dfs(int u,int s)
{
ans=max(ans,s);
st[u]=1;
for(int i=h[u];~i;i=ne[i])
{
int y=e[i],z=w[i];
if(!st[y]) dfs(y,s+w[i]);
}
}
int main()
{
memset(h,-1,sizeof h);
int n;cin>>n;
n--;
while(n--)
{
int a,b,c;cin>>a>>b>>c;
add(a,b,c);add(b,a,c);
sum+=c;
}
dfs(1,0);
cout<<2*sum-ans;
}
G-武林秘籍
占个坑,等我变得像大三学长一样强了就补()

浙公网安备 33010602011771号