从05年通到08年,还在通的《畅通工程》(全四季)

第一季(并查集 2005

 

 

 

题目描述:

    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

输入:

    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1N编号。 

    注意:两个城市之间可以有多条道路相通,也就是说

    3 3

    1 2

    1 2

    2 1

    这种输入也是合法的

    当N0时,输入结束,该用例不被处理。

输出:

    对每个测试用例,在1行里输出最少还需要建设的道路数目。

样例输入:

4 2

1 3

4 3

3 3

1 2

1 3

2 3

5 2

1 2

3 5

999 0

0

样例输出:

1

0

2

998

来源:

2005年浙江大学计算机及软件工程研究生机试真题

 

//要注意 编号是从1开始的
#include<iostream>
using namespace std;
 
int Tree[1001];
 
int getroot(int x)
{
   if(Tree[x]==-1) return x;
   else {
          int temp=getroot(Tree[x]);
  Tree[x]=temp;
  return temp;
   }
}
 
int main()
{
   int n,m;
   while(cin>>n)
   {
   if(n==0)  break;
      cin>>m;
  int i;
  for(i=1;i<=n;i++)
  {
      Tree[i]=-1;
  }
      
  int a,b;
  for(i=1;i<=m;i++)
  {
     cin>>a>>b;
 a=getroot(a);
 b=getroot(b);
 
 if(a!=b)  
 {
Tree[a]=b;
 }
  }
 
  int sum=0;
  for(i=1;i<=n;i++)
  if(Tree[i]==-1) sum++;
  cout<<sum-1<<endl;
   }
 
   return 0;
}

 

 

 

 

 

 

 

 

第二季(最小生成树 2006

 

 

题目描述:

    某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

输入:

    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1N编号。

    当N0时,输入结束,该用例不被处理。

输出:

    对每个测试用例,在1行里输出最小的公路总长度。

样例输入:

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

样例输出:

3

5

来源:

2006年浙江大学计算机及软件工程研究生机试真题

 

 

#include<iostream>
#include<algorithm>
using namespace std;
 
struct edge
{
   int b,e,w;
};
 
 
int Tree[101];
edge Bian[6000];
 
int getroot(int x)
{
   if(Tree[x]==-1) return x;
   else {
          int temp=getroot(Tree[x]);
  Tree[x]=temp;
  return temp;
   }
}
 
 
bool cmp(edge A,edge B)
{
  return  A.w<B.w;
}
 
int main()
{
   int n;
   while(cin>>n)
   {
   if(n==0)  break;
      int i;
 
  for(i=1;i<=n;i++)
  Tree[i]=-1;
 
      int a,b;
  for(i=1;i<=n*(n-1)/2;i++)
  {
    cin>>Bian[i].b>>Bian[i].e>>Bian[i].w;
  }
      
  sort(Bian+1,Bian+1+n*(n-1)/2,cmp);
 int sum=0; 
  for(i=1;i<=n*(n-1)/2;i++)
  {
      a=getroot(Bian[i].b);
  b=getroot(Bian[i].e);
  if(a!=b)
  {
  Tree[a]=b;
              sum+=Bian[i].w;
  }
  }
 
  cout<<sum<<endl;
 
   }
 
   return 0;
}
 

 

 

 

第三季(最小生成树+可能不连通 2007

题目描述:

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

输入:

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

输出:

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

样例输入:

3 3

1 2 1

1 3 2

2 3 4

1 3

2 3 2

0 100

样例输出:

3

?

来源:

2007年浙江大学计算机及软件工程研究生机试真题

 

和上一题目差不多,注意nm的表示,就是多了个不连通的情况,即Treei= -1 不止一个。

 

 

#include<iostream>
#include<algorithm>
using namespace std;
 
struct edge
{
   int b,e,w;
};
 
 
int Tree[101];
edge Bian[101];
 
int getroot(int x)
{
   if(Tree[x]==-1) return x;
   else {
          int temp=getroot(Tree[x]);
  Tree[x]=temp;
  return temp;
   }
}
 
 
bool cmp(edge A,edge B)
{
  return  A.w<B.w;
}
 
int main()
{
   int n,m;
   while(cin>>n)
   {
   if(n==0)  break;
   cin>>m;
      int i;
 
  for(i=1;i<=m;i++)
  Tree[i]=-1;
 
      int a,b;
  for(i=1;i<=n;i++)
  {
    cin>>Bian[i].b>>Bian[i].e>>Bian[i].w;
  }
      
  sort(Bian+1,Bian+1+n,cmp);
 int sum=0; 
  for(i=1;i<=n;i++)
  {
      a=getroot(Bian[i].b);
  b=getroot(Bian[i].e);
  if(a!=b)
  {
  Tree[a]=b;
              sum+=Bian[i].w;
  }
  }
 
  bool tong=true;int x=2;
   for(i=1;i<=m;i++)
   {
      if(Tree[i]==-1) x--;
  if(x==0)
  {
    tong=false;
break;
  }
   }
 
   if(tong)
  cout<<sum<<endl;
   else
   cout<<"?"<<endl;
 
   }
 
   return 0;
}

 

 

 

第四季(最小生成树+路有些已经造好了 2008

 

 

题目描述:

    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

输入:

    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

 

    当N0时输入结束。

输出:

    每个测试用例的输出占一行,输出全省畅通需要的最低成本。

样例输入:

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

样例输出:

3

1

0

来源:

2008年浙江大学计算机及软件工程研究生机试真题

 

一个很巧妙的方法,就是把已经造好的路的权值改为0,其他和“第二季”的一模一样。

 

#include<iostream>
#include<algorithm>
using namespace std;
 
struct edge
{
   int b,e,w;
};
 
 
int Tree[101];
edge Bian[6000];
 
int getroot(int x)
{
   if(Tree[x]==-1) return x;
   else {
          int temp=getroot(Tree[x]);
  Tree[x]=temp;
  return temp;
   }
}
 
 
bool cmp(edge A,edge B)
{
  return  A.w<B.w;
}
 
int main()
{
   int n;
   while(cin>>n)
   {
   if(n==0)  break;
      int i;
 
  for(i=1;i<=n;i++)
  Tree[i]=-1;
 
      int a,b;
  for(i=1;i<=n*(n-1)/2;i++)
  {
 int bb;
    cin>>Bian[i].b>>Bian[i].e>>Bian[i].w>>bb;
if(bb==1)  Bian[i].w=0;
  }
      
  sort(Bian+1,Bian+1+n*(n-1)/2,cmp);
 int sum=0; 
  for(i=1;i<=n*(n-1)/2;i++)
  {
      a=getroot(Bian[i].b);
  b=getroot(Bian[i].e);
  if(a!=b)
  {
  Tree[a]=b;
              sum+=Bian[i].w;
  }
  }
 
  cout<<sum<<endl;
 
   }
 
   return 0;
}
 
posted @ 2015-01-18 14:44  小爷  阅读(252)  评论(0编辑  收藏  举报