跳过正文
  1. Posts/

POJ 1849 Two (树的直径)

·2 分钟

题目链接

题意:一棵树。。然后初始两个推雪机在点s,问如何选择路径使得处理完所有边上的积雪所耗费的汽油最少(走过一条有雪的边和一条没雪的边耗费的汽油一样)

思路:很容易想到,我们应该尽可能不走已经被清理过雪了的边,因为这样很浪费。。。这样不难想到应该是和树的直径有关。但是初始的位置是给定的。。。怎么办?突然发现由于是给了两个推雪机。。所以其实相当于。。。只有一个推雪机&我们可以从任意位置开始推雪。。。第二个问题是。。。对于不在直径上的边。。我们怎么算cost?解决办法是读边的时候进行记录。。。然后求直径的时候记录路径。。。对于一条边。。。只要有一个点不在直径上。。。那么这条边的代价就是2倍。。。

1A蛤蛤蛤

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年07月17日 星期日 19时04分49秒
  4File Name :code/poj/1849.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=1E5+7;
 34vector < pi > edge[N];
 35int n,s;
 36int lst;
 37int beg;
 38int d[N];
 39bool vis[N];
 40bool onpath[N];
 41int path[N];
 42int ans;
 43
 44struct  Edge
 45{
 46    int u,v,w;
 47
 48}e[N];
 49void init( int n)
 50{
 51    for ( int i = 1 ; i <= n ; i++) edge[i].clear();
 52    ms(path,-1);
 53    ms(onpath,false);
 54}
 55
 56void bfs( int s)
 57{
 58    ms(d,0);
 59    ms(vis,false);
 60    queue<int>q;
 61    q.push(s);
 62    vis[s] = true;
 63
 64    while (!q.empty())
 65    {
 66	int u = q.front();
 67	q.pop();
 68
 69	int siz = edge[u].size();
 70
 71	for ( int i = 0 ;i  < siz;  i++)
 72	{
 73	    int v = edge[u][i].fst;
 74	    int w = edge[u][i].sec;
 75	    if (vis[v]) continue;
 76	    path[v] =  u;
 77	    vis[v] = true;
 78	    d[v] = d[u] + w;
 79	    q.push(v);
 80	}
 81    }
 82
 83}
 84int main()
 85{
 86	#ifndef  ONLINE_JUDGE
 87	freopen("code/in.txt","r",stdin);
 88  #endif
 89
 90
 91	cin>>n>>s;
 92	init(n);
 93	for ( int i = 1  ;i <= n-1 ; i ++)
 94	{
 95	    int u,v,w;
 96	    scanf("%d%d%d",&u,&v,&w);
 97	    e[i].u = u;
 98	    e[i].v = v;
 99	    e[i].w = w;
100	    edge[u].push_back(make_pair(v,w));
101	    edge[v].push_back(make_pair(u,w));
102	}
103
104	bfs(1);
105	int mx = 0 ;
106	for ( int i = 1 ; i <= n ; i ++)
107	    if (d[i]>mx)
108	    {
109		mx = d[i];
110		lst = i;
111	    }
112
113	mx = 0 ;
114	ms(path,-1);
115	bfs(lst);
116
117	for ( int i = 1 ; i <= n ; i++)
118	    if (d[i]>mx)
119	    {
120		mx = d[i];
121		beg = i ;
122	    }
123
124	ans = mx;
125	int x = beg;
126	//cout<<"bfs ok?"<<endl;
127	while (x!=-1)
128	{
129	    //cout<<"x:"<<x<<endl;
130	    onpath[x] = true;
131	    x = path[x];
132	}
133
134//	cout<<"ans:"<<ans<<endl;
135	for ( int i = 1 ; i <= n-1 ; i++)
136	{
137	    int u = e[i].u;
138	    int v = e[i].v;
139	    int w = e[i].w;
140	    if (onpath[u]&&onpath[v]) continue;
141	    ans +=w*2;
142	}
143
144	printf("%d\n",ans);
145
146
147
148  #ifndef ONLINE_JUDGE
149  fclose(stdin);
150  #endif
151    return 0;
152}

相关文章

hdu 4607 Park Visit (树的直径,推公式)

·2 分钟
hdu4607题目链接 题意:给出一棵树。。。边权都为1. m个查询。。每个查询给一个k,表示只访问k个点。。。问每次的最小路径和是多少。。。 思路:我们发现。。会使路径和变大的一个不利因素是折返。。也就是访问某景点后。。必须要回去才能继续前进。。这样的距离是2倍。。那为了使得路径和尽可能小。。我们就尽量不要访问这样的点。。。而不是这样的点一定在直径上。。。以及我们还发现。。。不在直径上的点。。 。。不管深度如何(深度的意思是说,与和该点最近的直径上的点的距离),距离的贡献是一样的。。都是2倍。。所以我们可以推出一个公式。。。如果树的直径是d,那么k<=d+1的时候,答案为k-1,否则答案为d+(k-d-1)*2。。。

hdu 2196 Computer (树的直径||树形dp)

·4 分钟
hdu2196 题意:给出一棵树。。。求距离每个点的最远距离是多少。。。 思路:最远距离什么的。。能想到树的直径。。。但是有什么关系呢? 我们在求树的直径的时候。。。直径的两个端点是可以知道的。。。如果再从两个端点分别做两次bfs。。。每个点取两个距离的较大值就是答案。。。。?