山东财经大学新生赛暨天梯赛选拔赛-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-武林秘籍

占个坑,等我变得像大三学长一样强了就补()

posted @ 2022-03-19 20:22  Hssliu  阅读(34)  评论(0)    收藏  举报