HDU 1879 继续畅通工程(kruskal,prim)

来源:互联网 发布:手机计算道路软件 编辑:程序博客网 时间:2024/06/04 18:28

继续畅通工程

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

Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

当N为0时输入结束。

Output
每个测试用例的输出占一行,输出全省畅通需要的最低成本。

Sample Input
3
1 2 1 0
1 3 2 0
2 3 4 0
3
1 2 1 0
1 3 2 0
2 3 4 1
3
1 2 1 0
1 3 2 1
2 3 4 1
0

Sample Output
3
1
0

题解:最小生成树krusal,prim算法

代码:kruskal

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#define INF 0x3f3f3fusing namespace std;const int maxn = 10000+5;struct node{    int s;    int e;    int c;    bool operator < (const node &a)    {        return c<a.c;    }}map[maxn];int n,m,pre[maxn];void init(){    for(int i=1;i<=n;i++)        pre[i]=i;}int find(int x){    int r=x;    while(r!=pre[r])        r=pre[r];    return r;}void mix(int x,int y){    int fx=find(x);    int fy=find(y);    if(fx!=fy)        pre[fy]=fx;}int kruskal(){    sort(map,map+m);    node no;    int ans=0;    for(int i=0;i<m;i++)    {        no=map[i];        if(find(no.s)!=find(no.e))        {            mix(no.s,no.e);            ans +=no.c;        }    }    return ans;}int main(){    while(cin>>n&&n)    {        int state;        m=n*(n-1)/2;        for(int i=0;i<m;i++)        {            scanf("%d%d%d%d",&map[i].s,&map[i].e,&map[i].c,&state);///刚开始用的cin一直超时(气哭==)            if(state)                map[i].c=0;            else                continue;        }        init();        cout<<kruskal()<<endl;    }    return 0;}

网上的prim算法做的

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;int n;int low[110];//存储将要联通的候选边int visited[110];//是否已经并入联通集合int map[110][110];//二维矩阵存储图const int maxn=0x3fffffff;//无穷大int prim(){    int min;    int pos=0,ans=0;    memset(visited,0,sizeof(visited));    visited[pos]=1;//从第一个点开始联通    for(int i=0;i<n;i++)//循环初始化    {        if(!visited[i])        {            low[i]=map[pos][i];        }    }    for(int i=1;i<n;i++)    {        min=maxn;        for(int j=0;j<n;j++)        {            if(min>low[j]&&!visited[j])            {                min=low[j];//找到所有可连通边中的最短边                pos=j;//找到将要并入的下一个点            }        }        ans+=min;        visited[pos]=1;        for(int j=0;j<n;j++)//新点并入后更新最短边候选集合        {            if(map[pos][j]<low[j])                low[j]=map[pos][j];        }    }    return ans;}int main(){    while(scanf("%d",&n)!=EOF)    {         if(!n)break;        int a,b,c,d;        int m=(n-1)*n/2;        for(int i=0;i<m;i++)        {         scanf("%d%d%d%d",&a,&b,&c,&d);         if(d)//若两点已经连通,不需新建道路,花费为零         {            map[a-1][b-1]=map[b-1][a-1]=0;         }        else             map[a-1][b-1]=map[b-1][a-1]=c;        }        printf("%d\n",prim());    }    return 0;}
0 0
原创粉丝点击