HDU 1233 还是畅通工程【最小生成树】

来源:互联网 发布:仿猪八戒源码 编辑:程序博客网 时间:2024/05/16 04:39

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1233

也可以看看我另外一个博客

最小生成树 

Prim():代码上跟Dijkstra神似 93MS

#include<stdio.h>#include<string.h>int vist[103],map[103][103],n;#define max 10000int prim(){int pri[100];int i,j,k,temp,res=0;for(i=1;i<=n;i++)pri[i] = map[1][i];vist[1]=1;//起始点vist过for(i=1;i<n;i++)//n个顶点有n-1条边{temp = max;for(j=1;j<=n;j++){if(!vist[j] && pri[j] < temp){temp = pri[j];k = j;}}res += temp;//这里不同vist[k] = 1;for(j=1;j<=n;j++){if(!vist[j] &&  map[k][j] < pri[j] )//条件不同pri[j] = map[k][j];}}return res;}int main(){int i,j,a,b,c;freopen("a.txt","r",stdin);while(scanf("%d",&n)!=EOF && n){memset(vist,0,sizeof(vist));for(i=1;i<=n;i++){for(j=1;j<=n;j++)map[i][j] = max;map[i][i] = 0;}for(j=0;j<n*(n-1)/2;j++){scanf("%d%d%d",&a,&b,&c);map[a][b] = map[b][a] = c;}printf("%d\n",prim());}return 0;}


裸克鲁斯卡尔 156MS

#include <cstdio>#include <string.h>#include <iostream>#include <algorithm>using namespace std;int vis[105],n;#define MAX 150000int arc;struct node{    int u,v,w;}edge[10005];bool cmp(node a,node b){    return a.w < b.w;}int solve(){int i,j,k,res;res = 0;    k = 0;for(i=0;i<arc;i++){        int tu = edge[i].u;        int tv = edge[i].v;        int v1 = vis[tu];        int v2 = vis[tv];if(v1!=v2)        {            res+=edge[i].w;            for(j=1;j<=n;j++)                if(vis[j]==v2)                    vis[j] = v1;        }}return res;}int main(){int dis;//freopen("1.in","r",stdin);while(scanf("%d",&n) != EOF,n){    int k=0;    arc = n*(n-1)/2;for(int i=1;i<=n;i++)            vis[i] = i;for(int j=0;j<arc;j++)        {            scanf("%d%d%d",&edge[k].u,&edge[k].v,&edge[k].w);            k++;        }        sort(edge,edge+arc,cmp);        printf("%d\n",solve());    }return 0;}

并查集kruskal 171MS

#include <cstdio>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int maxn = 105;const int maxm = 10005;int father[maxn], n, arc;struct node {    int u, v, w;} edge[maxm];bool cmp(node a, node b) {    return a.w < b.w;}int find(int x) {    if (x != father[x]) father[x] = find(father[x]);    return father[x];}void merge(int x, int y) {    x = find(x);    y = find(y);    if (x != y) {        father[x] = y;    }}int kruskal() {    sort(edge, edge + arc, cmp);    for (int i = 1; i <= n; i++)        father[i] = i;    int ans = 0;    for (int i = 0; i < arc; i++) {        int tu = edge[i].u;        int tv = edge[i].v;        int v1 = find(tu);        int v2 = find(tv);        if (v1 != v2) { //边的两端点不在一个分量里才选之            ans += edge[i].w;            merge(tu, tv);        }    }    return ans;}int main() {    std::cout.sync_with_stdio(false);    while (cin>>n, n) {        arc = n * (n - 1) / 2;        for (int i = 0; i < arc; i++) {            cin >> edge[i].u >> edge[i].v >> edge[i].w;        }        cout<<kruskal()<<endl;    }    return 0;}


纯并查集解法

#include<cstdio>#include<algorithm>using namespace std;#define MAX 5005int father[MAX];typedef struct node{int x,y,cost;}node;node a[MAX];int find(int x){if( x != father[x] )father[x] = find(father[x]);return father[x];}int merge(int x,int y){x = find(x);y = find(y);if(x != y)    {        father[x] = y;        return 1;    }    return 0;}int cmp(node a,node b){return a.cost < b.cost;//升序}int main(){int i,n,m;int res;//freopen("1.txt","r",stdin);while(scanf("%d",&n),n){    int m=n*(n-1)/2;for(i=1;i<=n;i++)father[i] = i;for(i=1;i<=m;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].cost);sort(a+1,a+m+1,cmp);//排序目的:当a点可以和b、c点组成集合时优先和成本低的组合res = 0;for(i=1;i<=m;i++){if(merge(a[i].x,a[i].y))                res += a[i].cost;}        printf("%d\n",res);}return 0;}


POJ 2377 最大生成树:法一直接改数据和条件即可。法二:把值都弄成负数,再加进去求最小生成树,最后取反

#include <cstdio>#include <cmath>#include <cstring>#include <set>#include <stack>#include <queue>#include <vector>#include <iostream>#include <algorithm>using namespace std;#define ll long long#define INF 0x7FFFFFFF#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define CLR( a , x ) memset ( a , x , sizeof (a) )#define RE freopen("1.in","r",stdin);#define WE freopen("1.out","w",stdout);#define debug(x) cout<<#x<<":"<<(x)<<endl;const int inf = 0x3f;int n,m;int mat[1005][1005];int prim(int s){    int dis[1005];    int vis[1005];    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++)        dis[i]=mat[s][i];    dis[s]=0;    vis[s]=1;    int ans=0;    for(int i=0;i<n-1;i++)    {        int tmp=-1;        int k;        for(int j=1;j<=n;j++)        {            if(!vis[j]&&dis[j]>tmp)            {                k=j;                tmp=dis[j];            }        }        vis[k]=1;        if(tmp==-1)    return -1;        ans+=tmp;        for(int j=1;j<=n;j++)        {            if(!vis[j]&&mat[k][j]>dis[j])                dis[j]=mat[k][j];        }    }    return ans;}int main(){//    WE    int a,b,c;    while(cin>>n>>m)    {        memset(mat,-1,sizeof(mat));        REP(i,m)        {            cin>>a>>b>>c;            mat[b][a]=mat[a][b]=max(mat[a][b],c);        }        int ans=prim(n);        cout<<ans<<endl;    }return 0;}
#include <cstdio>#include <cmath>#include <cstring>#include <set>#include <stack>#include <queue>#include <vector>#include <iostream>#include <algorithm>using namespace std;#define ll long long#define INF 0x7FFFFFFF#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define CLR( a , x ) memset ( a , x , sizeof (a) )#define RE freopen("1.in","r",stdin);#define WE freopen("1.out","w",stdout);#define debug(x) cout<<#x<<":"<<(x)<<endl;const int inf = 0x3f;int n,m;int mat[1005][1005];int prim(int s){    int dis[1005];    int vis[1005];    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++)        dis[i]=mat[s][i];    dis[s]=0;    vis[s]=1;    int ans=0;    for(int i=0;i<n-1;i++)    {        int tmp=inf;        int k;        for(int j=1;j<=n;j++)        {            if(!vis[j]&&dis[j]<tmp)            {                k=j;                tmp=dis[j];            }        }        vis[k]=1;        if(tmp==inf)    return -1;        ans+=tmp;        for(int j=1;j<=n;j++)        {            if(!vis[j]&&mat[k][j]<dis[j])                dis[j]=mat[k][j];        }    }    return ans;}int main(){//    RE    int a,b,c;    while(cin>>n>>m)    {        memset(mat,0x3f,sizeof(mat));        REP(i,m)        {            cin>>a>>b>>c;            mat[b][a]=mat[a][b]=min(mat[a][b],-c);        }        int ans=prim(n);        if(ans==-1)            cout<<"-1\n";        else            cout<<-ans<<endl;    }return 0;}



0 0