树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。
二叉树是树的特殊一种,包括满二叉树,完全二叉树,排序二叉树。
特点: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 ;
}