HDU 4313
这个题有两种做法
1.并查集
初始时一条边都不加,将所有边按权值从大到小排序,然后依次判断每一个边两端的顶点是否是均为machine节点,如果是则应删除这条边,否则加入这条边,然后在并查集合并时尽量让根节点为machine节点。
[cpp]
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int cnt;
int n,k;
ll sum;
bool is[100100];
int fa[100100];
struct Edge{
int from,to,cost;
}edge[100100];
void addedge(int s,int t,int c){
edge[cnt].from=s;
edge[cnt].to=t;
edge[cnt++].cost=c;
}
void init(){
cnt=0;
memset(is,0,sizeof(is));
for(int i=0;i<n;i++)
fa[i]=i;
sum=0;
}
bool cmp(struct Edge a,struct Edge b){
return a.cost<b.cost;
}
int query(int i){
if(fa[i]!=i)
fa[i]=query(fa[i]);
return fa[i];
}
void merge(int a,int b){
int aa=query(a);
int bb=query(b);
if(is[bb])
fa[aa]=bb;
else
fa[bb]=aa;
}
int main(){
int t,T,i,j,u,v,w,uu,vv;
int tem,p,q;
bool flag;
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%d %d",&n,&k);
init();
for(i=1;i<n;i++){
scanf("%d %d %d",&u,&v,&w);
addedge(u,v,w);
}
for(i=1;i<=k;i++){
scanf("%d",&tem);
is[tem]=1;
}
sort(edge,edge+cnt,cmp);
for(i=cnt-1;i>=0;i--){
flag=0;
uu=query(edge[i].from);
vv=query(edge[i].to);
if(uu!=vv && is[uu] && is[vv])
flag=1;
if(flag){
sum+=edge[i].cost;
//printf("****%d %d %d\n",i,edge[i].from,edge[i].to);
}
else
merge(edge[i].from,edge[i].to);
}
cout<<sum<<endl;
}
}
2.树形DP
这里dis[i]数组保存的是从i节点向下走到machine节点的最小边权,如果i节点本身为machine节点,那么dis[i]=MAX.
当前的根节点如果是machine节点,那么与根节点相连的所有能走到machine节点的节点的都要删去。
当前的根节点如果是machine节点,那么要留下一个删除费用最大的节点用于向上更新。
[cpp]
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
const long long MAX=(~(0ULL)>>1);
typedef long long ll;
int cnt,head[100100];
int n,k;
ll sum;
bool is[100100];
ll dis[100100];
vector<ll>vec[100100];
struct Edge{
int to,cost,next;
}edge[200100];
void addedge(int s,int t,int c){
edge[cnt].to=t;
edge[cnt].next=head[s];
edge[cnt].cost=c;
head[s]=cnt++;
edge[cnt].to=s;
edge[cnt].next=head[t];
edge[cnt].cost=c;
head[t]=cnt++;
}
void init(){
cnt=0;
memset(head,-1,sizeof(head));
memset(is,0,sizeof(is));
sum=0;
for(int i=0;i<n;i++)
vec[i].clear();
}
ll mini(ll a,ll b){
return a>b?b:a;
}
void dfs(int s,int father){
int i,j;
int all=0;
ll s1=0,s2=0;
for(i=head[s];i!=-1;i=edge[i].next){
j=edge[i].to;
if(j!=father){
dfs(j,s);
if(is[j])
vec[s].push_back(mini(dis[j],edge[i].cost));
}
}
if(vec[s].size()==0){
dis[s]=MAX;
return;
}
sort(vec[s].begin(),vec[s].end());
for(i=0;i<vec[s].size()-1;i++)
sum+=(ll)vec[s][i];
if(is[s]){
sum+=(ll)v
补充:软件开发 , C++ ,