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

来源:互联网 发布:安卓版windows模拟器 编辑:程序博客网 时间:2024/05/16 11:52

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 10001using 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);}}

原创粉丝点击