hdu 1863 最小生成树

来源:互联网 发布:重庆mac专柜在哪里 编辑:程序博客网 时间:2024/06/05 22:39

http://acm.hdu.edu.cn/showproblem.php?pid=1863

还是最小生成树,还是用了kruskal写,就是有点不一样的地方在于,他要让你判断是否能够保证畅通,也就是是否能有最小生成树,其实就是判断是不是连通图吧,因为连通图一定会有最小生成树。

一开始我的想法是,先进行一次并查集的合并与查找,看一下有几个集合,如果只有一个集合的话就是连通图,肯定有最小生成树存在,如果多余一个集合就不会有,直接输出问好。之后要记得还原根节点。。

附上代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define M 1000000int u[M],v[M],p[M],w[M];int r[M],t[M];int n,m;int ans;int cmp(int a,int b){    return w[a] < w[b];}int find(int x){    return p[x]==x?x:p[x]=find(p[x]);}void uni(int x,int y){    if(x!=y)        p[x] = y;}int kruskal(){    for(int i = 0;i < n;i++)    {        int e = r[i];        int x = find(u[e]),y = find(v[e]);        if(x!=y)        {            p[x] = y;            ans += w[e];        }    }}int main(){    while(scanf("%d %d",&n,&m)==2 && n)    {        memset(t,0,sizeof(t));        ans = 0;        int num = 0;        for(int i = 1;i <= m;i++) p[i] = i;        for(int i = 0;i < n;i++) r[i] = i;        for(int i = 0;i < n;i++)        {            scanf("%d%d%d",&u[i],&v[i],&w[i]);            uni(u[i],v[i]);        }        for(int i = 1;i <=m;i++)        {            int temp = find(i);            if(t[temp]==0)            {                num++;                t[temp]++;            }        }        if(num!=1)        {            printf("?\n");            continue;        }        for(int i = 1;i <= m;i++)            p[i] = i;        sort(r,r+n,cmp);        kruskal();        printf("%d\n",ans);    }    return 0;}

因为最小生成树的边一定是n-1条边,那么其实我们还可以计算一下边数,在将找到的边加入最小生成树的时候顺便做就行了,那么如果这个边数小于n-1的话,肯定就不是连通图没有最小生成树。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define M 1000000int u[M],v[M],p[M],w[M];int r[M],t[M];int n,m;int ans;int cmp(int a,int b){    return w[a] < w[b];}int find(int x){    return p[x]==x?x:p[x]=find(p[x]);}bool kruskal(){    int sum = 0;    for(int i = 0;i < n;i++)    {        int e = r[i];        int x = find(u[e]),y = find(v[e]);        if(x!=y)        {            p[x] = y;            ans += w[e];            sum++;        }    }    if(sum < m-1)        return false;    return true;}int main(){    while(scanf("%d %d",&n,&m)==2 && n)    {        memset(t,0,sizeof(t));        ans = 0;        int num = 0;        for(int i = 1;i <= m;i++) p[i] = i;        for(int i = 0;i < n;i++) r[i] = i;        for(int i = 0;i < n;i++)        {            scanf("%d%d%d",&u[i],&v[i],&w[i]);        }        sort(r,r+n,cmp);        bool ok = kruskal();        if(ok)        printf("%d\n",ans);        else        printf("?\n");    }    return 0;}


0 0
原创粉丝点击