POJ or HDU以前做过的题目整理(树形DP)
POJ 1849 Two
题目链接:http://poj.org/problem?id=1849
题意:给你一棵树,每条边都有权值,给你两个人去遍历这棵树,问将这棵树遍历完的最小代价是多少,给定两个人的起点,两个人不一定要回到起点。
思路:但是如果不回来,则所走路径中有一条简单路径是可以只走一遍的,派出了两个点去遍历,也就是说有两条简单路径是可以直走一边的,我们要使这两条简单路径的总和尽可能的长,就转换为了树的最长路径问题了,所以答案就为总的边权和的两倍减去树的最长路。
otherwords:求出所有的边的权值和2倍,然后减去树的直径。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
using namespace std;
typedef long long LL;
const int N = 100005;
vector<pair<int,int> > g[N];
int vis[N],dist[N];
int bfs(int &s)
{
int mac = 0;
memset(vis,0,sizeof(vis));
queue<int> que;
que.push(s);
dist[s] = 0;
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
using namespace std;
typedef long long LL;
const int N = 100005;
vector<pair<int,int> > g[N];
int vis[N],dist[N];
int bfs(int &s)
{
int mac = 0;
memset(vis,0,sizeof(vis));
queue<int> que;
que.push(s);
dist[s] = 0;
vis[s] = 1;
while(!que.empty())
{
int now = que.front();
que.pop();
for(int i=0; i<g[now].size(); i++)
{
int v = g[now][i].first;
int w = g[now][i].second;
if(vis[v])
continue;
dist[v] = dist[now] + w;
if(dist[v] > mac)
mac = dist[v],s = v;
vis[v] = 1;
que.push(v);
}
}
return mac;
}
int main()
{
//freopen("in.txt","r",stdin);
int n,s,a,b,w;
while(scanf("%d%d",&n,&s)!=EOF)
{
int sum = 0;
for(int i=0; i<n-1; i++)
{
scanf("%d%d%d",&a,&b,&w);
sum += 2 * w;
g[a].push_back(make_pair(b,w));
g[b].push_back(make_pair(a,w));
}
bfs(s);
int mac = bfs(s);
printf("%d\n",sum - mac);
}
return 0;
}
while(!que.empty())
{
int now = que.front();
que.pop();
for(int i=0; i<g[now].size(); i++)
{
int v = g[now][i].first;
int w = g[now][i].second;
if(vis[v])
continue;
dist[v] = dist[now] + w;
if(dist[v] > mac)
mac = dist[v],s = v;
vis[v] = 1;
que.push(v);
}
}
return mac;
}
int main()
{
//freopen("in.txt","r",stdin);
int n,s,a,b,w;
while(scanf("%d%d",&n,&s)!=EOF)
{
int sum = 0;
for(int i=0; i<n-1; i++)
{
scanf("%d%d%d",&a,&b,&w);
sum += 2 * w;
g[a].push_back(make_pair(b,w));
g[b].push_back(make_pair(a,w));
}
bfs(s);
int mac = bfs(s);
printf("%d\n",sum - mac);
}
return 0;
}

浙公网安备 33010602011771号