标签:
http://acm.hdu.edu.cn/showproblem.php?pid=4313
1 5 3 2 1 8 1 0 5 2 4 5 1 3 4 2 4 0
10HintNeo can destroy the road connecting city 2 and city 4 of weight 5 , and the road connecting city 0 and city 1 of weight 5. As only one road can be destroyed at a time, the total minimum time taken is 10 units of time. After destroying these roads none of the Machines can reach other Machine via any path.
/**
hdu 4313 并查集+贪心
题目大意:
给定n(n<=100000)个节点的树,每条边有一定的权值,有m个点是危险的,现在想将树分成m块使得每块中恰好只有一个危险的点,问最小的花费是多少。
解题思路:
类似Kruskal的贪心过程,将节点按照从小到大排序,以每个危险的节点为并查集的根节点
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=100005;
struct note
{
int u,v;
LL w;
bool operator < (const note &other) const
{
return w>other.w;
}
} edge[maxn];
int father[maxn];
bool flag[maxn];
int n,m;
void init()
{
for(int i=0; i<=n; i++)
{
father[i]=i;
}
}
int find(int u)
{
if(u==father[u])
return u;
return father[u]=find(father[u]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<n-1; i++)
{
int u,v;
LL w;
scanf("%d%d%I64d",&edge[i].u,&edge[i].v,&edge[i].w);
}
memset(flag,false,sizeof(flag));
for(int i=0; i<m; i++)
{
int u;
scanf("%d",&u);
flag[u]=true;
}
init();
LL sum=0;
sort(edge,edge+n-1);
for(int i=0; i<n-1; i++)
{
int x=find(edge[i].u);
int y=find(edge[i].v);
if(flag[x]&&flag[y])
{
sum+=edge[i].w;
}
else if(flag[x])
{
father[y]=x;
}
else
{
father[x]=y;
}
}
printf("%I64d\n",sum);
}
return 0;
}
/**
hdu 4313 树形dp
题目大意:
给定n(n<=100000)个节点的树,每条边有一定的权值,有m个点是危险的,现在想将树分成m块使得每块中恰好只有一个危险的点,问最小的花费是多少。
解题思路:
dp[i][0]代表的是在当前以i节点为根节点的子树中,i所在的连通块中没有危险节点的最小花费;
dp[i][1]代表的是在当前以i节点为根节点的子树中,i所在的连通块中有危险节点的最小花费;
如果i是叶子节点:如果i为危险点dp[i][0] = inf,dp[i][1]= 0;否则dp[i][0] = 0,dp[i][1] = inf;
如果i不是叶子节点:如果i是危险点dp[i][0] = inf , dp[i][1] = sigma min(dp[son][0],dp[son][1]+w);
否则dp[i][0] = sigma min(dp[son][0],dp[son][1]+w),dp[i][1] = min(dp[i][0] – min(dp[son][0],dp[son][1]+w)+dp[son][1])。
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=100005;
const LL inf=0x3fffffffffffffffLL;
int head[maxn],ip;
LL dp[maxn][2];
int n,m;
bool flag[maxn];
struct note
{
int v,next;
LL w;
} edge[maxn*2];
void init()
{
memset(head,-1,sizeof(head));
ip=0;
}
void addedge(int u,int v,LL w)
{
edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++;
}
void dfs(int u,int pre)
{
/// printf("%d->%d\n",pre,u);
if(flag[u])
{
dp[u][0]=inf;
dp[u][1]=0;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
LL w=edge[i].w;
if(v==pre)continue;
dfs(v,u);
dp[u][1]+=min(dp[v][0],dp[v][1]+w);
}
return;
}
else
{
dp[u][0]=0;
dp[u][1]=inf;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
LL w=edge[i].w;
if(v==pre) continue;
dfs(v,u);
dp[u][0]+=min(dp[v][0],dp[v][1]+w);
}
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
LL w=edge[i].w;
if(v==pre)continue;
dp[u][1]=min(dp[u][1],dp[u][0]-min(dp[v][0],dp[v][1]+w)+dp[v][1]);
}
return;
}
}
/**void dfs1(int u,int pre)
{
printf("%d->%d\n",pre,u);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre)continue;
dfs1(v,u);
}
}*/
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1; i<n; i++)
{
int u,v;
LL w;
scanf("%d%d%I64d",&u,&v,&w);
u++;
v++;
addedge(u,v,w);
addedge(v,u,w);
// printf("%d-->%d\n",u,v);
// printf("%d-->%d\n",v,u);
}
memset(flag,false,sizeof(flag));
for(int i=0; i<m; i++)
{
int x;
scanf("%d",&x);
x++;
flag[x]=true;
}
dfs(1,-1);
//dfs1(1,-1);
/**for(int i=1;i<=n;i++)
{
printf("%d %I64d %I64d\n",i,dp[i][0],dp[i][1]);
}*/
printf("%I64d\n",min(dp[1][0],dp[1][1]));
}
return 0;
}标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/43113005