HDU_Steps 6.1 生成树 HDU1102 HDU1162 HDU1232 HDU1233 HDU1879 HDU1301 HDU3371 HDU3367

HDU_STEPS 6.1 最小生成树

 

6.1.1 HDU 1102 Constructing Roads 裸的最小生成树

6.1.2 HDU 1162 Eddy's picture 最小生成树,每两点直接连线建图

6.1.3 HDU 1232 畅通工程 用并查集将图分块,然后修N-1条路即可

6.1.4 HDU 1233 还是畅通工程 还是最小生成树

6.1.5 HDU 1879 继续畅通工程 在已生成部分图的情况下生成最小生成树,输入的时候用并查集合并已经连接的端点

6.1.6 HDU 1301 Jungle Roads 将字母转换成数字建图即可,还是最小生成树

6.1.7 HDU 3371 Connect the Cities

先用并查集将地图分块,连接N块要N-1条路.然后用克鲁斯卡耳生成最小生成树,每合并一次计数加1,说明修了1条路,如果最后修的路的条数<n-1,说明不连通

#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
struct edge{
	int u,v,w;
	bool operator <(const edge& ee)const{return w<ee.w;} 
}e[25005];
int p[505],cas,n,m,k,hash[505];
int find(int x){return x==p[x]?x:p[x]=find(p[x]);}
int main(){
	scanf("%d",&cas); 
	while(cas--){
		scanf("%d%d%d",&n,&m,&k);
		
		for(int i=1;i<=n;i++)p[i]=i;
		memset(hash,0,sizeof hash);
		
		for(int i=0;i<m;i++)
			scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
		for(int i=0;i<k;i++){
			int t,st,en;
			scanf("%d%d",&t,&st);t--;
			while(t--){
				scanf("%d",&en);
				p[find(st)]=find(en);	
			}	
		}
		int tot=0,cnt=0;
		for(int i=1;i<=n;i++)
			if(!hash[find(i)])tot++,hash[find(i)]=1;
		tot--;//需要增加的边的条数 
			 
		sort(e,e+m);
		
		int res=0;
		for(int i=0;i<m;i++){
			int x=find(e[i].u),y=find(e[i].v);	
			if(x==y)continue;
			res+=e[i].w;
			p[x]=y;
			cnt++;
			if(cnt==tot)break;//已经连通了 
		}
		
		if(cnt<tot)printf("-1\n");
		else printf("%d\n",res);
	}
}

6.1.8 HDU 3367 Pseudoforest

求一个最大生成森林,每个连通块里至多只有一个环

先贪心按从大到小对边排序。如果并入的两个点在一个集合中并且这个集合没有环,就并入这个点并将这个集合标记为有环;如果两个点在不同集合且都有环,就不能加这条边;如果只有一个有环,则并入有环的那部分

#include <cstdio>
#include <algorithm>
#include <cmath>
#define MAXN 10001
using namespace std;
struct edge{
	int u,v,w,us;
	edge(){};
	edge(int a,int b,int c){u=a,v=b,w=c,us=0;}
	bool operator<(const edge& e)const{return w>e.w;}	
}e[MAXN*10];
int p[MAXN],n,m,cir[MAXN]; 
int find(int x){return x==p[x]?x:p[x]=find(p[x]);}
int main(){
	while(scanf("%d%d",&n,&m),n||m){
		for(int i=0;i<n;i++)p[i]=i;
		memset(cir,0,sizeof cir);
		
		for(int i=0;i<m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
		
		sort(e,e+m);
		int res=0;
		for(int i=0;i<m;i++){
			int x=find(e[i].u),y=find(e[i].v);
			if(x==y&&cir[x]==0){//如果两点在同一个块且无环 
				cir[x]=1;
				res+=e[i].w;
			}
			if(cir[x]&&cir[y])continue;//如果都有环就不能连了 
			if(cir[x])p[y]=x;//如果x有环,将y并入x中 
			else p[x]=y;	//否则将x并入y中 
			res+=e[i].w;			
		}

		printf("%d\n",res);
	}
}

你可能感兴趣的:(c,ini)