HDOJ 1879

来源:互联网 发布:xp系统网络共享设置 编辑:程序博客网 时间:2024/05/19 08:26

题目大意:

         输入一个N,表示村庄的数目,接下来输入N*(N-1)/2行,每行输入4个数,分别表示每条道路的起始端点,终止端点,花费代价,修成状态。求出是所有村庄连通的最小代价。

算法思想:

       依旧采用克鲁斯卡尔算法,但是求解问题时需要注意道路的修成状态,如果状态为1则在用克鲁斯卡尔算法之前就该把这条边加入集合A中,或者修改该条道路的代价为0,然后在求解该问题。解题时还需要注意输入采用scanf(),不然会超时。

代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN=6000;typedef struct{     int start;      int end;     int value;     int flag;}Edge;int node[100];int Find_set(int n){    if(node[n]==-1)return n;    return node[ n]=Find_set(node[n]);}Edge road[MAXN];bool cmp(Edge a,Edge b){    if(a.value<b.value) return true;    return false;}bool Merge(int a,int b){     int r1=Find_set(a);     int r2=Find_set(b);     if(r1==r2) return false;//注意细节问题,这里==而不是=!!!!!!!!!!!     if(r1<r2) node[r2]=r1;     if(r2<r1) node[r1]=r2;     return true;}int Kruskal(int N,int M,int num){    int cost=0;     sort(road,road+M,cmp);    for(int i=0;i<M;i++){        if(Merge(road[i].start,road[i].end)){            num++;             cost+=road[i].value;                    }       if(num==N-1) break;    }    return cost;}int main(){    int N;    int num,cost;    while(scanf("%d",&N)!=EOF&&N){       int M=(N*(N-1))/2;       memset(node,-1,sizeof(node));       cost=0;       num=0;       for(int i=0;i<M;i++){        scanf("%d%d%d%d",&road[i].start,&road[i].end,&road[i].value,&road[i].flag);        if(road[i].flag){            Merge(road[i].start,road[i].end);            num++;             //road[i].value=0;(此方法比较妙直接将费用清零就可以了)         }       }       cost=Kruskal(N,M,num);       printf("%d\n",cost);    }    return 0;}


0 0
原创粉丝点击