冬训练习5

来源:互联网 发布:魔兽世界mac版插件 编辑:程序博客网 时间:2024/06/05 21:53

A。欧拉回路

欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?

Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结
束。
Output
每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
Sample Input
3 31 21 32 33 21 22 30
Sample Output
10

欧拉回路 

学习到了如何判断无向图的连通性

使用并查集

看看最后父节点有几个  只有一个的话就为连通的

并查集最后一般是循环 father[i]==i 来判断各种关系

无向图欧拉回路条件:

1.连通 2.度全为奇数

编程实现如下

#include<iostream>
#include<cstdio>


using namespace std;


const int maxV=1000;
const int maxE=maxV*maxV/2+7;
int degree[maxV+7];
int pre[maxV+7];
int E,V;


void init(){
for(int i=1;i<=maxV;i++) pre[i]=i;
}


int find(int x){
int temp;
for(temp=x;pre[temp]!=temp;temp=pre[temp]);
while(x!=temp){
int t=pre[x];
pre[x]=temp;
x=t;
}
return temp;
}


void mix(int x,int y){
int fx=find(x), fy=find(y);
if(fx!=fy) pre[fx]=fy;
}
bool isEuler(){
for(int i=1;i<=V;i++){
if(degree[i]&1) return false;
}
return true;
}


bool isConnct(){
int cnt=0;
for(int i=1;i<=V;i++)
if(pre[i]==i) cnt++;
if(cnt==1) return true;
return false;
}


int main(){
while(~scanf("%d",&V)&&V){
scanf("%d",&E);
memset(degree,0,sizeof(degree));
init();
for(int i=1;i<=E;i++){
int fr,to;
scanf("%d%d",&fr,&to);
degree[fr]++;
degree[to]++;
mix(fr,to);
}
// if(isConnct()) cout<<"Y"<<endl;
if(isConnct()&&isEuler()) cout<<1<<endl;
else cout<<0<<endl;
}
return 0;
}



B.还是畅通工程

某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。 
Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。 
当N为0时,输入结束,该用例不被处理。 
Output
对每个测试用例,在1行里输出最小的公路总长度。 
Sample Input
31 2 11 3 22 3 441 2 11 3 41 4 12 3 32 4 23 4 50
Sample Output
35          Huge input, scanf is recommended.
Hint
Hint

方法思路是:

这道题目是求最小生成树

使用kruskal算法

每次取最小的边  ,判断这条边的两个节点是否已经取了,用并查集来维护

取了之后就加入并查集中

取权值最小的边,可以有多种方法,用优先队列,把边都放到优先队列中(超时)

用vector(超时) 用数组(156ms)就可以过



#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;


int father[105];


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


int find(int x){
int temp;
for(temp=x;father[temp]!=temp;temp=father[temp]);
while(x!=temp){
father[x]=temp;
x=father[x];
}
return temp;
}


void merge(int u,int v){
int x=find(u);
int y=find(v);
if(x!=y) 
father[x]=y;
}


class ss{
public:
int s,e,w;
friend bool operator < (const ss&a,const ss& o){
return a.w<o.w;
}
};


ss vec[100005];
int main(){
int n;
while(scanf("%d",&n)&&n){
int num=n*(n-1)/2;
int i;
for(i=0;i<num;i++){
scanf("%d%d%d",&vec[i].s,&vec[i].e,&vec[i].w);
}
for(i=1;i<=n;i++)
father[i]=i;
int ans=0;
sort(vec,vec+num);
/*while(!que.empty()){
ss tmp=que.top();
que.pop();
int s=tmp.s,e=tmp.e,w=tmp.w;
int x=find(s),y=find(e);
if(x!=y){
ans+=w;
father[x]=y;
}
}*/
for(i=0;i<num;i++){
ss tmp=vec[i];
int s=tmp.s,e=tmp.e,w=tmp.w;
int x=find(s),y=find(e); 
if(x!=y){
ans+=w;
father[x]=y;
}
}
printf("%d\n",ans);
//cout<<ans<<endl;
}
return 0;
}


0 0
原创粉丝点击