hdu 畅通工程系列题目

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232

并查集水。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N = 1000;
int n,m;
int father[N];

int _find(int x){
    if(x==father[x]) return x;
    return _find(father[x]);
}

int main(){
    while(scanf("%d",&n)!=EOF,n){
        for(int i=1;i<=n;i++){
            father[i] = i;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            int x = _find(a);
            int y = _find(b);
            father[x] = y;
        }
        int ans = 0;
        for(int i=1;i<=n;i++){
            if(father[i]==i) ans++;
        }
        printf("%d\n",ans-1);
    }
}

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

kruskal水

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N = 105;
int n,m;
int father[N];
struct Edge{
    int s,e,len;
}edge[N*(N-1)/2];
int _find(int x){
    if(x==father[x]) return x;
    return _find(father[x]);
}
int cmp(Edge a,Edge b){
    return a.len<b.len;
}
int kruskal(int m){
    sort(edge+1,edge+m+1,cmp);
    int cost = 0;
    for(int i=1;i<=m;i++){
        int x = _find(edge[i].s);
        int y  = _find(edge[i].e);
        if(x!=y){
            father[x] = y;
            cost+=edge[i].len;
        }
    }
    return cost;
}
int main(){
    while(scanf("%d",&n)!=EOF,n){
        for(int i=1;i<=n;i++){
            father[i] = i;
        }
        int m = n*(n-1)/2;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&edge[i].s,&edge[i].e,&edge[i].len);
        }
        printf("%d\n",kruskal(m));
    }
}

 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1863

kruskal水+判断强连通分量

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int M = 105;
const int N = M*(M-1)/2;
struct Edge{
    int s,e,len;
}edge[N];
int father[M],n,m;
int _find(int x){
    if(x==father[x]) return x;
    return _find(father[x]);
}
int cmp(Edge a,Edge b){
    return a.len<b.len;
}
int kruskal(int m){
    sort(edge+1,edge+m+1,cmp);
    int cost = 0;
    for(int i=1;i<=m;i++){
        int x = _find(edge[i].s);
        int y = _find(edge[i].e);
        if(x!=y){
            father[x] = y;
            cost += edge[i].len;
        }
    }
    return cost;
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF,n){
        for(int i=1;i<=m;i++) father[i] = i;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&edge[i].s,&edge[i].e,&edge[i].len);
        }
        int cost = kruskal(n);
        int ans = 0;
        for(int i=1;i<=m;i++){
            if(father[i]==i) ans++;
        }
        if(ans==1) printf("%d\n",cost);
        else printf("?\n");
    }
}

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1875

将平面上的点都连接起来求最小生成树最后再判断一下强连通分量。

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N = 105;
const double eps = 1e-8;
struct Point{
    int x,y;
}p[N];
struct Edge{
    int s,e;
    double len;
}edge[N*(N-1)/2];
int father[N];
int n;
int _find(int x){
    if(x==father[x]) return x;
    return _find(father[x]);
}
double dis(Point a,Point b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool check(double k){
    if(k+eps<10) return false;
    if(k-eps>1000) return false;
    return true;
}
int cmp(Edge a,Edge b){
    return a.len<b.len;
}
double kruskal(int m){
    sort(edge+1,edge+m+1,cmp);
    double cost = 0;
    for(int i=1;i<=m;i++){
        int x = _find(edge[i].s);
        int y = _find(edge[i].e);
        if(x!=y){
            father[x] = y;
            cost +=edge[i].len;;
        }
    }
    return cost;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;i++) father[i] = i;
        for(int i=0;i<n;i++){
            scanf("%d%d",&p[i].x,&p[i].y);
        }
        int m =1;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                double len = dis(p[i],p[j]);
                if(!check(len)) continue;
                edge[m].s = i;
                edge[m].e = j;
                edge[m++].len = dis(p[i],p[j]);
            }
        }
        m--;
        double cost = kruskal(m);
        int ans = 0;
        for(int i=0;i<n;i++){
            if(father[i]==i) ans++;
        }
        if(ans==1) printf("%.1lf\n",cost*100);
        else printf("oh!\n");
    }
}

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1879

处理一下输入,kruskal水

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N = 105;
struct Edge{
    int s,e,len;
}edge[N*(N-1)/2];
int n,m;
int father[N];
int _find(int x){
    if(x==father[x]) return x;
    return _find(father[x]);
}
int cmp(Edge a,Edge b){
    return a.len<b.len;
}
int kruskal(int m){
    sort(edge+1,edge+m+1,cmp);
    int cost = 0;
    for(int i=1;i<=m;i++){
        int x = _find(edge[i].s);
        int y = _find(edge[i].e);
        if(x!=y){
            father[x] = y;
            cost+=edge[i].len;
        }
    }
    return cost;
}
int main(){
    while(scanf("%d",&n)!=EOF,n){
        for(int i=1;i<=n;i++) father[i] = i;
        int m = n*(n-1)/2;
        for(int i=1;i<=m;i++){
            int c,d;
            scanf("%d%d%d%d",&edge[i].s,&edge[i].e,&c,&d);
            if(!d) edge[i].len=c;
            else edge[i].len =0;
        }
        printf("%d\n",kruskal(m));
    }
}

 

posted @ 2016-05-07 21:12  樱花庄的龙之介大人  阅读(362)  评论(0编辑  收藏  举报