HDU 畅通工程(I,II,III)

树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。
二叉树是树的特殊一种,包括满二叉树,完全二叉树,排序二叉树。
特点:1、每个结点最多有两个子树,结点的度最大为2。
2、左子树和右子树次序不能颠倒。
3、即使某结点只有一个子树,也要区分左右子树

畅通工程 I

Description
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
Output
对每个测试用例,在1行里输出最少还需要建设的道路数目。
Sample Input
5 3
1 2
3 2
4 5
0
Sample Output
1

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 1e3+10;
int array[maxn];
int city_n,road_m,u,v,ans;
int find(int x)
{
    if(x == array[x])
        return x;
    else
        return find(array[x]);
}
void fun(int x,int y)
{
    int m = find(x);
    int n = find(y);
    if(m != n)
        array[m] = n;
}
int main()
{
    ios::sync_with_stdio(false);//关闭 标准输入流的同步
    while(cin>>city_n>>road_m)
    {
        if(city_n==0)
            break;
        memset(array,0,sizeof array);//初始化函数
        for(int i=1; i<=city_n; i++)
            array[i] = i;
        for(int i=1; i<=road_m; i++)
        {
            cin>>u>>v;
            fun(u,v);
        }
        ans=0;
        for(int i=1; i<=city_n; i++)
        {
            if(array[i] == i)
                ans++;
        }
        cout<<ans-1<<endl;
    }
    return 0;
}

畅通工程 II (还是畅通工程)

**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
浙大计算机研究生复试上机考试-2006年**

分析:提题意相当于给你一个完全图,让你从中选出一个子图,使得所有的村庄又能互通,那么就相当于找一颗最小生成树

kruskal算法实现(加边法)

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
//#include <unordered_map>
#include <map>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <utility>
#include <cstring>
//#include <multimap>
//#include <multiset>
#define ll long long
#define inf 0x3f3f3f3f
const long long INF = 0x3f3f3f3f3f3f3f3f ;
using namespace std;
const int mxn = 2e5+10 ;
#define TLE std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ls now<<1,l,mid
#define rs now<<1|1,mid+1,r
#define lc now<<1
#define rc now<<1|1
#define upsum(now) rt[now].sum =rt[now<<1].sum + rt[now<<1|1].sum ;
#define upmx(now) rt[now].mx = max(rt[now<<1].mx , rt[now<<1|1].mx) ;
#define pb push_back
int n,m,k,t,sum[mxn],far[mxn];
string str ;
int prime[mxn], isprime[mxn];
struct edge
{
    int u,v,w;
    bool operator <(const edge & x) const
    {
        return x.w>w;
    }
}edge[mxn];
int Findroot(int x)
{
    if(x==far[x]) return far[x] ;
    return far[x] = Findroot( far[x] );
}
void kruskal()
{
    int ans = 0 ;
    for(int i=1;i<=n*(n-1)/2;i++)
    {
        int u_root = Findroot( edge[i].u );
        int v_root = Findroot( edge[i].v );
        if(u_root != v_root)
        {
            far[ v_root ] = u_root ;
            ans+=edge[i].w ;
        }
    }
    cout<<ans<<endl;
}
int main()
{
    TLE;
    while(cin>>n&&n)
    {
        for(int i=1;i<=n*(n-1)/2;i++)
            cin>>edge[i].u>>edge[i].v>>edge[i].w ;
        sort(edge+1,edge+1+n*(n-1)/2);
        for(int i=0;i<=n;i++)
            far[i] = i ;
        kruskal();
    }
    return 0 ;
}

prim算法(加点法)

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
//#include <unordered_map>
#include <map>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <utility>
#include <cstring>
//#include <multimap>
//#include <multiset>
#define ll long long
#define inf 0x3f3f3f3f
const long long INF = 0x3f3f3f3f3f3f3f3f ;
using namespace std;
const int mxn = 105+10 ;
#define TLE std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ls now<<1,l,mid
#define rs now<<1|1,mid+1,r
#define lc now<<1
#define rc now<<1|1
#define upsum(now) rt[now].sum =rt[now<<1].sum + rt[now<<1|1].sum ;
#define upmx(now) rt[now].mx = max(rt[now<<1].mx , rt[now<<1|1].mx) ;
#define pb push_back
int n,m,k,t,u,v,w,dis[mxn],edge[mxn][mxn];
bool vis[mxn];
string str ;
int prime[mxn], isprime[mxn];
void prim()
{
    for(int i=1;i<=n;i++)
        dis[i]=edge[1][i] ;
    int ans = 0 ;
    memset(vis,false,sizeof(vis));
    dis[1] = 0 ;vis[1] = true;
    for(int i=2;i<=n;i++)
    {
        int tmp = inf , index ;
        for(int j=1;j<=n;j++)
        {
            if(tmp>dis[j] && !vis[j])
            {
                index = j ;
                tmp = dis[j] ;
            }
        }
        if(tmp==inf) break;
        vis[index] = true ;
        ans+=tmp;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j] && dis[j]>edge[index][j])
                dis[j] = edge[index][j] ;
        }
    }
    cout<<ans<<endl;
}
int main()
{
    TLE;
    while(cin>>n&&n)
    {
        for(int i=1;i<=n*(n-1)/2;i++)
        {
            cin>>u>>v>>w ;
            edge[u][v]=edge[v][u] = w ;
        }
        prim();
    }
    return 0 ;
}

畅通工程续
**Problem Description
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。

Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.

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

Sample Output
2
-1**

Dijkstra

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <functional>
//#include <unordered_map>
#include <map>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <utility>
#include <cstring>
//#include <multimap>
//#include <multiset>
#define ll long long
#define inf 0x3f3f3f3f
const long long INF = 0x3f3f3f3f3f3f3f3f ;
using namespace std;
const int mxn = 1000+10 ;
#define TLE std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ls now<<1,l,mid
#define rs now<<1|1,mid+1,r
#define lc now<<1
#define rc now<<1|1
#define upsum(now) rt[now].sum =rt[now<<1].sum + rt[now<<1|1].sum ;
#define upmx(now) rt[now].mx = max(rt[now<<1].mx , rt[now<<1|1].mx) ;
#define pb push_back
int n,m,k,t,u,v,w,dis[mxn],G[mxn][mxn];
bool vis[mxn];
string str ;
int prime[mxn], isprime[mxn];
void dijkstra()
{
    cin>>u>>v;
    for(int i=0;i<=n;i++)
        dis[i] = G[u][i] ;
    memset(vis,false,sizeof(vis));
    vis[u] = true ;
    for(int i=0;i<=n*n;i++)
    {
        int tmp = inf , index ;
        for(int j=0;j<=n;j++)
        {
            if(!vis[j] && tmp>dis[j])
            {
                tmp = dis[j] ;
                index = j ;
            }
        }
        if( tmp == inf ) break;
        vis[index] = true ;
        for(int j=0;j<=n;j++)
        {
            if(!vis[j] && dis[j] > dis[index]+G[index][j])
                dis[j] = dis[index]+G[index][j] ;
        }
    }
    cout<<(dis[v]==inf ? -1 : dis[v] )<<endl;
}
int main()
{
    TLE;
    while(cin>>n>>m)
    {
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                G[i][j] = i==j? 0:inf;
        for(int i=1;i<=m;i++)
        {
            cin>>u>>v>>w;
            if(G[u][v]>w)
                G[u][v]=G[v][u]=w;
        }
        dijkstra();
    }
    return 0 ;
}

**Floyd() **

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <functional>
//#include <unordered_map>
#include <map>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <utility>
#include <cstring>
//#include <multimap>
//#include <multiset>
#define ll long long
#define inf 0x3f3f3f3f
const long long INF = 0x3f3f3f3f3f3f3f3f ;
using namespace std;
const int mxn = 1000+10 ;
#define TLE std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ls now<<1,l,mid
#define rs now<<1|1,mid+1,r
#define lc now<<1
#define rc now<<1|1
#define upsum(now) rt[now].sum =rt[now<<1].sum + rt[now<<1|1].sum ;
#define upmx(now) rt[now].mx = max(rt[now<<1].mx , rt[now<<1|1].mx) ;
#define pb push_back
int n,m,k,t,u,v,w,dis[mxn],G[mxn][mxn];
bool vis[mxn];
string str ;
int prime[mxn], isprime[mxn];
void dijkstra()
{
    cin>>u>>v;
    for(int i=0;i<=n;i++)
        dis[i] = G[u][i] ;
    memset(vis,false,sizeof(vis));
    vis[u] = true ;
    for(int i=0;i<=n*n;i++)
    {
        int tmp = inf , index ;
        for(int j=0;j<=n;j++)
        {
            if(!vis[j] && tmp>dis[j])
            {
                tmp = dis[j] ;
                index = j ;
            }
        }
        if( tmp == inf ) break;
        vis[index] = true ;
        for(int j=0;j<=n;j++)
        {
            if(!vis[j] && dis[j] > dis[index]+G[index][j])
                dis[j] = dis[index]+G[index][j] ;
        }
    }
    cout<<(dis[v]==inf ? -1 : dis[v] )<<endl;
}
void Floyd()
{
    cin>>u>>v;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            for(int k=0;k<n;k++)
                if( G[i][j] > G[i][k]+G[k][j] )
                    G[i][j] =  G[i][k]+G[k][j] ;
        }
    }

    cout<<(G[u][v]==inf?-1:G[u][v])<<endl;
}
int main()
{
    TLE;
    /// cout<<(int)(0xfffffff)<<endl;
    while(cin>>n>>m)
    {
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                G[i][j] = i==j? 0:inf;
        for(int i=1;i<=m;i++)
        {
            cin>>u>>v>>w;
            if(G[u][v]>w)
                G[u][v]=G[v][u]=w;
        }
        /// dijkstra();
        Floyd() ;
    }
    return 0 ;
}
发布了94 篇原创文章 · 获赞 29 · 访问量 8568

猜你喜欢

转载自blog.csdn.net/m0_43382549/article/details/86709988