最小生成树

来源:互联网 发布:网络机顶盒能接音响吗 编辑:程序博客网 时间:2024/06/04 23:31

最小生成树

                                                                             Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                                                           Total Submission(s): 113    Accepted Submission(s): 11


Problem Description
ap最近学习了最小生成树树之后,向你提了这么一个问题:给一个n个节点的完全图,节点编号从1-n, 如果限制这个完全图的生成树中k个点的度数为1,那么还能否构造出最小生成树呢?
 

Input
第一行一个正整数T,代表有T组数据
每组数据,第一个两个正整数n, k (2 <= n <= 300, 0 <= k <= n)
接下来n*(n-1)/2行,每行三个正整数ui, vi, wi, 代表节点ui和节点vi之间有一条权值为wi的边 (0 <= wi <= 10000)
最后一行, k个互不相同的数fi, 代表限制度数为1的节点的编号
输入保证给出的是完全图
 

Output
每组数据,若符合条件的最小生成树存在,输出该最小生成树所有边权之和; 若不存在, 输出-1
 

Sample Input
33 01 2 12 3 23 1 33 11 2 12 3 23 1 323 31 2 12 3 23 1 31 2 3
 

Sample Output
34-1
 

解题思路:若度为一的点是所有点,当n等于2的时候,答案就是唯一边权,否则就是形不成最小生成树,若度为一的点小于顶点数,那么先将度不为一的点用最小边连起来,再找和度为一的点最近的边(边的连点都为度为一的点是不能取的)


#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <vector>#include <set>#include <bitset>#include <stack>#include <map>#include <climits>#include <functional>using namespace std;#define LL long longconst int INF=0x3f3f3f3f;struct node{    int s,e,w,flag;}x[90000];int k,a[350];int f[350],n;int sum[350];int Find(int x){    if(f[x]==x) return x;    return f[x]=Find(f[x]);}bool cmp(node a,node b){    return a.w<b.w;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int p;        memset(a,0,sizeof a);        scanf("%d %d",&n,&k);        for(int i=1;i<=(n-1)*n/2;i++)            scanf("%d %d %d",&x[i].s,&x[i].e,&x[i].w),x[i].flag=0;        for(int i=1;i<=k;i++)            scanf("%d",&p),a[p]=1;        if(n==k)        {            if(n==2) {printf("%d\n",x[1].w);continue;}            else printf("-1\n");        }        for(int i=1;i<=n;i++) f[i]=i;        memset(sum,0,sizeof sum);        sort(x+1,x+1+n*(n-1)/2,cmp);        int cnt=0,ans=0;        for(int i=1;i<=(n-1)*n/2;i++)        {            if(a[x[i].s]) continue;            if(a[x[i].e]) continue;            int ss=Find(x[i].s),ee=Find(x[i].e);            if(ss!=ee)            {                f[ss]=ee;                cnt++;                ans+=x[i].w;                x[i].flag=1;            }            if(cnt==n-1) break;        }        for(int i=1;i<=(n-1)*n/2;i++)        {            if(cnt==n-1) break;            if(x[i].flag) continue;            if(a[x[i].s]&&a[x[i].e]) continue;            if(a[x[i].s]&&sum[x[i].s]) continue;            if(a[x[i].e]&&sum[x[i].e]) continue;            int ss=Find(x[i].s),ee=Find(x[i].e);            if(ss!=ee)            {                if(a[x[i].s]) sum[x[i].s]++;                else if(a[x[i].e]) sum[x[i].e]++;                f[ss]=ee;                cnt++;                ans+=x[i].w;            }            if(cnt==n-1) break;        }        printf("%d\n",ans);    }    return 0;}

0 0
原创粉丝点击