zoukankan      html  css  js  c++  java
  • 【APIO2010T2】巡逻-贪心+树形DP

    测试地址:巡逻

    做法:贪心,对于K=1的情况下,只需要找树的直径(树上最长的路径),设这个直径为len,则结果为2*(n-1)-len+1。对于K=2的情况,先找树的一个直径,将答案总数tot赋值为2*(n-1)-len+1,然后把直径上所有边赋值为-1,再求一遍直径,结果为tot-len+1。不过需要注意,直径最开始要赋值为0,因为如果直径为负数,还不如在一个点上绕自环。至于直径的求法,当然就是DFS啦!存储从一点到叶节点的最长的两条不重合的路径,并用下一层的信息修正上一层,也是类似树形DP的思想。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,k,mx[100010]={0},smx[100010]={0},mxp[100010]={0},smxp[100010]={0};
    int first[100010]={0},tot=0,ans,mp,smp,mi;
    bool vis[100010]={0};
    struct edge {int v,d,next;} e[200010];
    
    void insert(int a,int b,int d)
    {
      e[++tot].v=b;e[tot].d=d;e[tot].next=first[a];first[a]=tot;
    }
    
    void dfs(int v)
    {
      vis[v]=1;
      mx[v]=smx[v]=0,mxp[v]=smxp[v]=v;
      for(int i=first[v];i;i=e[i].next)
        if (!vis[e[i].v])
    	{
    	  dfs(e[i].v);
    	  if (mx[e[i].v]+e[i].d>mx[v])
    	  {
    	    smx[v]=mx[v],mx[v]=mx[e[i].v]+e[i].d;
    	    smxp[v]=mxp[v],mxp[v]=mxp[e[i].v];
    	  }
    	  else if (mx[e[i].v]+e[i].d>smx[v])
    	  {
    	    smx[v]=mx[e[i].v]+e[i].d,smxp[v]=mxp[e[i].v];
    	  }
    	}
    }
    
    bool del(int v)
    {
      bool flag=0;
      vis[v]=1;
      for(int i=first[v];i;i=e[i].next)
        if (!vis[e[i].v])
    	{
    	  if (del(e[i].v))
    	  {
    	    e[i].d=-1;
    	    flag=1;
    	  }
    	}
      if (v==mp||v==smp||flag) return 1;
      else return 0;
    }
    
    int main()
    {
      scanf("%d%d",&n,&k);
      for(int i=1,a,b;i<n;i++)
      {
        scanf("%d%d",&a,&b);
    	insert(a,b,1),insert(b,a,1);
      }
      
      dfs(1);
      int ans=0;
      for(int i=1;i<=n;i++)
      {
    	if (mx[i]+smx[i]>ans)
    	{
    	  mi=i;
    	  mp=mxp[i];
    	  smp=smxp[i];
    	}
    	ans=max(ans,mx[i]+smx[i]);
      }
      if (k==1) printf("%d",2*(n-1)-ans+1);
      else
      {
        int basic=2*(n-1)-ans+1;
    	ans=0;
    	memset(vis,0,sizeof(vis));
        del(mi);
    	memset(vis,0,sizeof(vis));
    	dfs(1);
    	for(int i=1;i<=n;i++)
    	{
    	  ans=max(ans,mx[i]+smx[i]);
    	}
    	printf("%d",basic-ans+1);
      }
      
      return 0;
    }
    


  • 相关阅读:
    [C/C++] 结构体内存对齐用法
    [其他] 关于C语言中使用未声明函数的问题
    [其他] 项目中的一个小问题
    【C++】DLL内共享数据区在进程间共享数据(重要)
    [MFC] CString小用例
    [C++] 频谱图中 FFT快速傅里叶变换C++实现
    [MFC] TabControl选项卡的使用
    [MFC] CFile读写文件实现(高效)
    [MFC] 编辑框 EditControl 输入数字范围限制
    [MFC] 对话框菜单项Menu选中打勾(单选,多选)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793795.html
Copyright © 2011-2022 走看看