spfa求树的直径

前言:本来想写在一个博文里的。
但是太麻烦了。并且dp还没怎么看懂。
还是要努力啊。
再写一下dfs求树的直径就完事了。;
方法:我感觉spfa在这里面和bfs几乎差不多,唯一的差别就是松弛除了赋初值就没啥用了。
hdu4607

#include <iostream>
#include <bits/stdc++.h>
/*这道题写废了我也很痛心啊,
怎么spfa又忘记了啊。
今天晚上targin肯定可以搞定。
这几天再把三个targin写写,数位dp和压缩那个玩意
就写写模拟.准备省赛吧亲
本体方法和bfs十分像。先求一个最远的。然后再根据那个最远的。在求一个最远的。
我剪短的证明一下。

不过这个spfa和bfs也太tm像了。松弛也没用。树形结构松弛个毛。
*/
using namespace std;
const int maxn=100008;
struct Node
{   int to,cost;
    Node(int a,int b){to=a;cost=b;};
    Node(){};
};
Node node[maxn];
int dis[maxn];
vector <Node> G[maxn];
void add(int a,int b,int c)
{   G[a].push_back(Node(b,c));
    //cout<<G[a].size()<<"尼玛?"<<endl;
   G[b].push_back(Node(a,c));
   //cout<<G[b].size()<<"kao"<<endl;
}
int spfa(int s)
{   queue<int>q;
    bool vis[maxn];
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));
      dis[s]=0;
     q.push(s);
     while(!q.empty())
     {   int u=q.front();
        //cout<<u<<"***"<<G[u].size()<<endl;
          q.pop();
          vis[u]=false;
         for(int i=0;i<G[u].size();i++)
         {    int s=G[u][i].to;

                 if(dis[s]>dis[u]+G[u][i].cost)
                {dis[s]=dis[u]+G[u][i].cost;
                if(!vis[s])
            {   vis[s]=true;
                q.push(s);}
                //cout<<G[u][i].cost<<"*****"<<endl;
                }

            //cout<<s<<"***"<<endl;

         }
     }
     return 0;
}
int main()
{    int m,n;
    int a,b,c;
      int t;
    scanf("%d",&t);
     while(t--)
          {    for(int i=0;i<100007;i++)
               G[i].clear();

               scanf("%d%d",&m,&n);
              for(int i=0;i<m-1;i++)
           {scanf("%d%d",&a,&b);
             add(a,b,1);

           }
          /*先求一个最远的点。然后在弄一遍。
          */
          /*for(int i=1;i<=m;i++)
          {for(int x=0;x<G[i].size();x++)
             cout<<G[i][x].to<<" ";
          cout<<endl;
          }*/

          int x=0;
          int la=0;
          spfa(1);
          //cout<<">>"<<endl;
          for(int i=1;i<=m;i++)
          {   if(x<dis[i]&&dis[i]!=0x3f3f3f3f)
               {  x=dis[i];
                  la=i;
               }
          }
      //for(int i=1;i<=m;i++)
          //cout<<dis[i]<<endl;

          //cout<<la<<endl;
          spfa(la);
          x=0;
           //for(int i=1;i<=m;i++)
          //cout<<dis[i]<<endl;
          for(int i=1;i<=m;i++)
          {    if(x<dis[i])
                 x=dis[i];
          }
          x++;
          int k;
       for(int i=1;i<=n;i++)
        {     scanf("%d",&k);
             if(k<=x)
                printf("%d\n",k-1);
             else
            printf("%d\n",(k-x)*2+x-1);}
      }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一次实验: 题目1 单链表相关算法的实验验证。 [实验目的] 验证单链表及其上的基本操作。 [实验内容及要求] 1、 定义单链表类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建单链表; 2)插入操作:分别在当前结点后、表头、表尾插入值为x的结点; 3)删除操作:分别删除表头结点、表尾结点和当前结点的后继结点; 4)存取操作:分别存取当前结点的值和单链表中第k个结点的值; 5)查找操作:查找值为x的元素在单链表中的位置(下标)。 题目2 分别给出堆栈、队列相关算法的实验验证。 [实验目的] 验证堆栈、队列及其上的基本操作。 [实验内容及要求](以队列为例) 1、 定义队列类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建队列; 2)插入操作:向队尾插入值为x的元素; 3)删除操作:删除队首元素; 4)存取操作:读取队首元素。 第二次实验 题目1 二叉相关算法的实验验证。 [实验目的] 验证二叉的链接存储结构及其上的基本操作。 [实验内容及要求] 1、 定义链接存储的二叉类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建一棵二叉,并对其初始化; 2)先根、中根、后根遍历二叉(递归算法); 3)在二叉中搜索给定结点的父结点; 4)搜索二叉中符合数据域条件的结点; 5)从二叉中删除给定结点及其左右子。 题目2 和森林的遍历算法的实验验证。 [实验目的] 验证和森林的遍历算法。 [实验内容及要求] 1、 定义左儿子—右兄弟链接存储的类和森林类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建和森林; 2)和森林的先根遍历的递归和迭代算法; 3)和森林的后根遍历的递归和迭代算法; 4)和森林的层次遍历算法。 题目3 二叉查找的验证实验。 [实验目的] 验证二叉查找及其相关操作。 [实验内容及要求] 1、 定义二叉查找的类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)实现二叉查找结构; 2) 实现二叉查找的查找、插入和删除等算法; 第三次实验 题目1 邻接表存储的图相关算法的实验验证。 [实验目的] 验证邻接表存的图及其上的基本操作。 [实验内容及要求] 1、 定义邻接表存储的图类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建一个邻接表存储的图; 2)返回图中指定边的权值; 3)返回图中某顶点的第一个邻接顶点; 4)返回图中某顶点关于另一个顶点的下一个邻接顶点的序号; 5)插入操作:向图中插入一个顶点,插入一条边; 6)删除操作:从图中删除一个顶点,删除一条边。 题目2 图的遍历算法的实验验证。 [实验目的] 验证图的遍历算法。 [实验内容及要求] 1、 定义邻接表存储的图。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建一个图; 2)图的深度优先遍历的递归算法; 3)图的深度优先遍历的迭代算法; 4)图的广度优先遍历算法。 第四次实验 折半插入排序,堆排序,快速排序 请阅读说明文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值