hdu 4313(类似于kruskal)

来源:互联网 发布:基本款斜挎包 知乎 编辑:程序博客网 时间:2024/06/07 01:44

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4313

思路:初始时一条边都不加,将所有边按权值从大到小排序,判断每一个边两端的顶点是否是均为machine节点,如果是则应删除这条边(即sum要加上这条边的权值),否则加入这条边,然后在并查集合并时尽量让根节点为machine节点。

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN 100010 7 typedef long long ll; 8 int n,k; 9 int parent[MAXN];10 bool mark[MAXN];11 struct Edge{12    int u,v,w;13 }edge[MAXN];14 ll sum;15 16 int cmp(const Edge &p,const Edge &q){17    return p.w>q.w;18 }19 20 int Find(int x){21    int s;22    for(s=x;s!=parent[s];s=parent[s])23    ;24    while(s!=x){25       int tmp=parent[x];26       parent[x]=s;27       x=tmp;28    }29    return s;30 }31 32 void Union(int u,int v){33    if(mark[u])parent[v]=u;34    else if(mark[v])parent[u]=v;35    else if(u<v)parent[v]=u;36    else parent[u]=v;37 }38 39 int main(){40    int _case,x;41 //   freopen("1.txt","r",stdin);42    scanf("%d",&_case);43    while(_case--){44       scanf("%d%d",&n,&k);45       for(int i=0;i<n-1;i++){46          scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);47          parent[i]=i;48       }49       parent[n-1]=n-1;50       sort(edge,edge+n-1,cmp);51       memset(mark,false,sizeof(mark));52       for(int i=1;i<=k;i++){ scanf("%d",&x);mark[x]=true; }53       sum=0;54       for(int i=0;i<n-1;i++){55          int u=Find(edge[i].u);56          int v=Find(edge[i].v);57          int w=edge[i].w;58          if(mark[u]&&mark[v]){59             sum+=w;60          }else61             Union(u,v);62       }63       printf("%I64d\n",sum);64    }65    return 0;66 }
View Code

 

0 0
原创粉丝点击