zoukankan      html  css  js  c++  java
  • 畅通工程,继续畅通工程,畅通工程再续,多种解法

    继续畅通工程

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


    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

    题解:

    方法一:克鲁斯卡尔算法;

    代码:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 const int MAXN=110;
     5 int sum;
     6 struct Node {
     7     int s,e,d,ol;
     8 };
     9     Node dt[MAXN*MAXN/2];
    10     int pre[MAXN];
    11 void initial(){
    12     memset(pre,0,sizeof(pre));
    13     memset(dt,0,sizeof(dt));
    14 }
    15 int find(int x){
    16     return pre[x]= x==pre[x]?x:find(pre[x]);
    17 }
    18 int cmp(const void *a,const void *b){
    19     if( (*(Node *)a).ol != (*(Node *)b).ol)return (*(Node *)b).ol-(*(Node *)a).ol;
    20     else return (*(Node *)a).d-(*(Node *)b).d;
    21 }
    22 void merge(Node a){
    23     int f1,f2;
    24     if(!pre[a.s])pre[a.s]=a.s;
    25     if(!pre[a.e])pre[a.e]=a.e;
    26         f1=find(a.s);
    27         f2=find(a.e);
    28 if(f1!=f2){
    29     pre[f1]=f2;
    30     if(!a.ol)sum+=a.d;
    31 }
    32 }
    33 int main(){
    34     int N,t;
    35     while(~scanf("%d",&N),N){
    36             initial();sum=0;
    37             t= N*(N-1)/2;
    38         int i,j;
    39             for(i=0;i<t;i++)
    40             scanf("%d%d%d%d",&dt[i].s,&dt[i].e,&dt[i].d,&dt[i].ol);
    41         qsort(dt,t,sizeof(dt[0]),cmp);
    42         for(int i=0;i<t;i++){
    43             merge(dt[i]);
    44         }
    45             printf("%d
    ",sum);
    46     }
    47     return 0;
    48 }

    方法二:prime:

    代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 const int INF=0x3f3f3f3f;
     4 const int MAXN=110;
     5 int vis[MAXN],map[MAXN][MAXN],low[MAXN];
     6 int N;
     7 void prime(){
     8     memset(vis,0,sizeof(vis));
     9     for(int i=1;i<=N;i++)low[i]=map[1][i];
    10     vis[1]=1;
    11     int k,temp,min=0;
    12     for(int i=1;i<=N;i++){
    13             temp=INF;
    14         for(int j=1;j<=N;j++)
    15         if(!vis[j]&&temp>low[j])temp=low[k=j];
    16 
    17         if(temp==INF){
    18             printf("%d
    ",min);
    19             break;
    20         }
    21         min+=temp;
    22         vis[k]=1;
    23         for(int j=1;j<=N;j++){
    24             if(!vis[j]&&low[j]>map[k][j])low[j]=map[k][j];
    25         }
    26     }
    27 }
    28 int main(){int a,b,c,d,M;
    29         while(~scanf("%d",&N),N){
    30                 M=N*(N-1)/2;
    31                 memset(map,INF,sizeof(map));
    32                 //printf("%d %d
    ",M,N);
    33                // for(int i=0;i<10;i++)for(int j=0;j<10;j++)printf("%d ",map[i][j]);
    34         while(M--){
    35             scanf("%d%d%d%d",&a,&b,&c,&d);
    36             if(d)map[a][b]=map[b][a]=0;
    37             else if(c<map[a][b])map[a][b]=map[b][a]=c;
    38             }
    39             prime();
    40         }
    41 return 0;
    42 }

    畅通工程

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 21373    Accepted Submission(s): 9196


    Problem Description
    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
     

    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
    行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
     

    Output
    对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
     

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

    Sample Output
    3 ?
     

    题解:

    方法一:克鲁斯卡尔算法;

    代码:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 struct Node {
     5 int s,e,dis;
     6 };
     7 Node road[110];
     8 int pre[110];
     9 int N,M;
    10 int cmp(const void *a,const void *b){
    11     return *(int *)a-*(int *)b;
    12 }
    13 int find(int x){
    14 return x==pre[x]?x:find(pre[x]);
    15 }
    16 bool merge(int x,int y){
    17 int f1,f2;
    18 f1=find(x);f2=find(y);
    19 if(f1!=f2){
    20     pre[f1]=f2;return true;
    21 }
    22 return false;
    23 }
    24 void initial(){memset(pre,0,sizeof(pre));}
    25 int main(){
    26     while(~scanf("%d%d",&N,&M),N){
    27         for(int i=0;i<N;i++)scanf("%d%d%d",&road[i].s,&road[i].e,&road[i].dis);
    28         qsort(road,N,sizeof(road[0]),cmp);
    29         int num=0;
    30         initial();
    31         for(int i=0;i<N;i++){
    32             if(!pre[road[i].s])pre[road[i].s]=road[i].s;
    33             if(!pre[road[i].e])pre[road[i].e]=road[i].e;
    34             if(merge(road[i].s,road[i].e))num+=road[i].dis;
    35         }int flot=0;
    36         for(int i=1;i<=M;i++){
    37             if(!pre[i]||i==pre[i])flot++;
    38             if(flot>1)break;
    39         }
    40         if(flot>1)puts("?");
    41         else printf("%d
    ",num);
    42     }
    43 return 0;}

    方法二:prime算法: 

     1 #include<stdio.h>
     2 #include<string.h>
     3 const int INF=0x3f3f3f3f;
     4 const int MAXN=110;
     5 int map[MAXN][MAXN],vis[MAXN],low[MAXN];
     6 int N,M,min;
     7 void prime(){
     8     memset(vis,0,sizeof(vis));//记得初始化
     9     int flot=1,k;
    10     for(int i=1;i<=M;i++)
    11         low[i]=map[1][i];//初始化low数组,刚开始已选集合{1}与此集合相连的权值为集合low
    12     vis[1]=1;//1在集合中visit【1】=1;
    13     for(int i=1;i<=M;i++){
    14             int temp=INF;//记得初始化;
    15         for(int j=1;j<=M;j++){//找最小权值;
    16             if(!vis[j]&&temp>low[j]){
    17                 temp=low[k=j];
    18             }
    19         }
    20         if(temp==INF){//找不到就判断;
    21             if(flot!=M)puts("?");
    22             else printf("%d
    ",min);
    23             break;
    24         }
    25                 min+=temp;
    26                 flot++;//代表当前已选集合中的元素个数;
    27                 vis[k]=1;
    28                 for(int i=1;i<=M;i++){//更新low数组;使其与已选数组相连的权值小;
    29                     if(!vis[i]&&low[i]>map[k][i])
    30                         low[i]=map[k][i];
    31                 }
    32         }
    33 }
    34 int main(){
    35     int a,b,d;
    36     while(~scanf("%d%d",&N,&M),N){
    37             min=0;//刚开始min忘初始化了。。。
    38             memset(map,INF,sizeof(map));//INF初始化为0xfffffff就不行,都是-1了
    39         //for(int i=0;i<10;i++)for(int j=0;j<10;j++)printf("%d ",map[i][j]);
    40        for(int i=0;i<N;i++){
    41             scanf("%d%d%d",&a,&b,&d);
    42             if(d<map[a][b])//此处不能少。。。
    43             map[a][b]=map[b][a]=d;
    44         }
    45         prime();
    46     }
    47 return 0;
    48 }

    畅通工程再续

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 46   Accepted Submission(s) : 20
    Problem Description
    相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
     
    Input
    输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
     
    Output
    每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
     
    Sample Input
    2 2 10 10 20 20 3 1 1 2 2 1000 1000
     
    Sample Output
    1414.2 oh!
    题解:qsort写错了,wa了无数次;也可以设个变量num=1;每加进一个点或者一个树时就num++最后与n比较,相等则连通;
    代码一:克鲁斯卡尔
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<math.h>
     4 #include<string.h>
     5 double distant(int ax,int ay,int bx,int by){
     6     int x=bx-ax,y=by-ay;
     7     double s;
     8     s=x*x+y*y;
     9     s=sqrt(s);
    10     return s;
    11 }
    12 int pre[110];
    13 struct Node{
    14         int s,e;
    15         double d;
    16 };
    17 Node die[10010];
    18 int find(int x){
    19     return pre[x]= x==pre[x]?x:find(pre[x]);
    20 }
    21 double minmoney;
    22 int cmp(const void *a,const void *b){
    23     if((*(Node *)a).d<(*(Node *)b).d)return -1;
    24     else return 1;
    25 }
    26 void merge(Node a){
    27     if(pre[a.s]==-1)pre[a.s]=a.s;
    28     if(pre[a.e]==-1)pre[a.e]=a.e;
    29     int f1=find(a.s),f2=find(a.e);
    30     if(f1!=f2){
    31         pre[f1]=f2;
    32         minmoney+=a.d;
    33     }
    34 }
    35 void initial(){
    36     memset(pre,-1,sizeof(pre));
    37     memset(die,0,sizeof(die));
    38 }
    39 int nx[110],ny[110];
    40 int main(){
    41         int T,C;
    42         scanf("%d",&T);
    43         while(T--){minmoney=0;
    44         initial();
    45        // for(int i=0;i<110;i++)printf("%d",pre[i]);
    46             scanf("%d",&C);
    47             for(int i=0;i<C;i++){
    48                 scanf("%d%d",&nx[i],&ny[i]);
    49             }
    50             int k=0;
    51             for(int i=0;i<C;i++){
    52                 for(int j=i+1;j<C;j++){
    53                     double dis=distant(nx[i],ny[i],nx[j],ny[j]);
    54                     //printf("%lf  ",dis);
    55                 if(dis>=10&&dis<=1000){
    56                     die[k].s=i;die[k].e=j;
    57                     die[k].d=dis;
    58                     k++;
    59                     }
    60                 }
    61             }
    62             //printf("%d
    ",k);
    63             qsort(die,k,sizeof(die[0]),cmp);
    64             for(int i=0;i<k;i++){
    65                 merge(die[i]);
    66             }
    67             int flot=0;
    68             for(int i=0;i<C;i++){
    69                 if(pre[i]==i||pre[i]==-1)flot++;
    70                 //if(flot>1)break;
    71             }
    72             //printf("%d
    ",flot);
    73             if(flot>1) puts("oh!");
    74             else printf("%.1lf
    ",minmoney*100);
    75         }
    76     return 0;
    77     }

     代码二:

    无语,又错了好久,然后发现初始化map出错,对于double数组不能像int那样初始化;

    代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<math.h>
     4 const int INF=0x3f3f3f3f;
     5 const int MAXN=110;
     6 int N,vis[MAXN];
     7 double map[MAXN][MAXN],low[MAXN];
     8 double fd(int ax,int ay,int bx,int by){
     9     int x=bx-ax;
    10     int y=by-ay;
    11     int s=x*x+y*y;
    12     return sqrt(s);
    13 }
    14 void prime(){
    15     int flot=1,k;
    16     double min=0,temp;
    17     memset(vis,0,sizeof(vis));
    18     vis[0]=1;
    19     for(int i=0;i<N;i++)
    20     {low[i]=map[0][i];}
    21     //printf("low  %lf 
    ",low[i]);}
    22     for(int i=0;i<N;i++){
    23             temp=INF;
    24         for(int j=0;j<N;j++){
    25             if(!vis[j]&&low[j]<temp)
    26                 temp=low[k=j];
    27         }
    28         // printf("***%d   %lf  ",temp,min);
    29         if(temp==INF){
    30             if(flot==N)printf("%.1lf
    ",min*100);
    31             else puts("oh!");
    32             break;
    33         }
    34         min+=temp;
    35         flot++;
    36         vis[k]=1;
    37         for(int j=0;j<N;j++){
    38             if(!vis[j]&&low[j]>map[k][j])
    39                 low[j]=map[k][j];
    40         }
    41     }
    42 }
    43 int main(){
    44         int T;
    45         int dx[MAXN],dy[MAXN];
    46         scanf("%d",&T);
    47             while(T--){
    48                 for(int i=0;i<MAXN;i++)
    49                     for(int j=0;j<MAXN;j++)
    50                     map[i][j]=INF;
    51                 scanf("%d",&N);
    52                 for(int i=0;i<N;i++)
    53                     scanf("%d%d",&dx[i],&dy[i]);
    54                 for(int i=0;i<N;i++)
    55                 for(int j=i+1;j<N;j++){
    56                     double dis=fd(dx[i],dy[i],dx[j],dy[j]);
    57                     //printf("### %d  %d %lf  ",i,j,dis);
    58                     if(dis<map[i][j]&&dis>=10&&dis<=1000)
    59                         map[i][j]=map[j][i]=dis;
    60                 }
    61                 /*for(int i = 0; i < N; ++i)
    62                     printf("%lf
    ", map[0][i]);*/
    63                 prime();
    64             }
    65     return 0;
    66 }

    畅通工程

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 44528    Accepted Submission(s): 23601

    Problem Description
    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 
     
    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。  注意:两个城市之间可以有多条道路相通,也就是说 3 3 1 2 1 2 2 1 这种输入也是合法的 当N为0时,输入结束,该用例不被处理。 
     
    Output
    对每个测试用例,在1行里输出最少还需要建设的道路数目。 
     
    Sample Input
    4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
     
    Sample Output
    1 0 2 998
    Hint
    Hint
    Huge input, scanf is recommended.
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define mem(x, y) memset(x, y, sizeof(x))
    const int MAXN = 1010;
    int pre[MAXN];
    void init(){
        mem(pre, -1);
    }
    int find(int x){
        return pre[x] = pre[x] == x?x:find(pre[x]);
    }
    void merge(){
        int x, y;
        scanf("%d%d", &x, &y);
        if(pre[x] == -1)pre[x] = x;
        if(pre[y] == -1)pre[y] = y;
        int f1 = find(x), f2 = find(y);
    //    printf("%d %d
    ", f1, f2);
        if(f1 != f2)
            pre[f1] = f2;
    }
    int work(){
        int n, m;
        init();
        scanf("%d", &n);
        if(!n)exit(0);
        scanf("%d", &m);
        while(m--){
            merge();
        }
        int cnt = 0;
    //    cout << n << endl;
        for(int i = 1; i <= n; i++){
            if(pre[i] == -1 || pre[i] == i)
                cnt++;
        //    cout << pre[i] << endl;
        }
        return cnt - 1;
    }
    int main(){
        while(1){
            printf("%d
    ", work());
        }
        return 0;
    }

    还是畅通工程

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 38162    Accepted Submission(s): 17236

    Problem Description
    某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
     
    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。 当N为0时,输入结束,该用例不被处理。
     
    Output
    对每个测试用例,在1行里输出最小的公路总长度。
     
    Sample Input
    3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0
     
    Sample Output
    3 5
    Hint
    Hint
    Huge input, scanf is recommended.
     
    Source
     
    代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define mem(x, y) memset(x, y, sizeof(x))
    const int MAXN = 10010;
    const int INF = 0x3f3f3f3f;
    struct Edge{
        int from, to, next, value;
        void init(int x, int y, int z, int d){
            from = x;
            to = y;
            next = z;
            value = d;
        }
    };
    Edge edg[MAXN << 1];
    int head[MAXN << 1];
    int edgnum;
    int vis[MAXN];
    int d[MAXN];
    int N;
    void init(){
        mem(head, -1);
        edgnum = 0;
    }
    void add(int a, int b, int c){
        Edge E;
        E.init(a, b, head[a], c);
        edg[edgnum] = E;
        head[a] = edgnum++;
    }
    int prim(){
        mem(d, INF);
        mem(vis, 0);
        vis[1] = 1;
        int ans = 0, cnt = 0;
        for(int i = head[1]; i != -1; i = edg[i].next)
            d[edg[i].to] = min(d[edg[i].to], edg[i].value);
        while(true){
            int k = -1;
            for(int i = 1; i <= N; i++){
                if(!vis[i] && (k == -1 || d[i] < d[k]))
                    k = i;
            }
            if(k == -1)break;
            ans += d[k];
            vis[k] = 1;
            for(int i = head[k]; i != -1; i = edg[i].next){
                d[edg[i].to] = min(d[edg[i].to], edg[i].value);
            }
        }
        return ans;
    }
    int main(){
        int a, b, c;
        while(~scanf("%d", &N), N){
            init();
            for(int i = 0; i < N * (N - 1)/2; i++){
                scanf("%d%d%d", &a, &b, &c);
                add(a, b, c);
                add(b, a, c);
            }
            printf("%d
    ", prim());
        }
        return 0;
    }
  • 相关阅读:
    div嵌套出现的样式问题
    知乎最多支持答案的黄色渐隐效果
    对话框图形的css实现方式
    排序算法的相关问题
    数据库优化
    常用的Java基本代码汇总
    浅谈getStackTrace()方法(一)
    ECharts学习总结(三)-----基本概念分析
    ECharts学习总结(二)-----图表组件漏斗图(funnel)
    Echarts学习总结(一)-----柱状图
  • 原文地址:https://www.cnblogs.com/handsomecui/p/4721060.html
Copyright © 2011-2022 走看看