poj - 2377 Bad Cowtractors&&poj 2395 Out of Hay(最大生成树)
2015-05-18 10:11
549 查看
http://poj.org/problem?id=2377
bessie要为FJ的N个农场联网,给出M条联通的线路,每条线路需要花费C,因为意识到FJ不想付钱,所以bsssie想把工作做的很糟糕,她想要花费越多越好,并且任意两个农场都需要连通,并且不能存在环。后面两个条件保证最后的连通图是一棵树。
输出最小花费,如果没办法连通所有节点输出-1.
最大生成树问题,按边的权值从大道小排序即可,kruskal算法可以处理重边的情况,但是在处理的时候,不能仅仅因为两个节点在同一个连通子图就判断图不合法,只是不需要处理这条边,也就是不要加入并查集即可,重边也是一样。
所以只要判断图是否连通即可,但是也不能因为单单判断每个节点是否被访问过,因为就算全部被访问,还是可能不会连通。
只要判断加入并查集的边的条数是否等于n-1即可。上面都是自己开始做的没想清楚或者导致wa的,所以写下来作为自己的一点想法。
http://poj.org/problem?id=2395
bessie打算去其他农场,这里总共有N个农场,她开始在1号农场,然后有M条双向连通的路,并且可能还有重边,所有的农场都至少有一条路和1号农场相连。去其他农场需要水所以需要一个水袋,但是不知道需要准备多大的袋子,已知每走一公里就会消耗一单元的水,并且每到一个农场就可以补充水,让你找出任意两个农场中距离最长的路,这样就能知道最少需要准备多大的袋子来装水。
扯了这么多 就是在最小生成树中找出路径最长的那一条边,比上面一题还简单。
bessie要为FJ的N个农场联网,给出M条联通的线路,每条线路需要花费C,因为意识到FJ不想付钱,所以bsssie想把工作做的很糟糕,她想要花费越多越好,并且任意两个农场都需要连通,并且不能存在环。后面两个条件保证最后的连通图是一棵树。
输出最小花费,如果没办法连通所有节点输出-1.
最大生成树问题,按边的权值从大道小排序即可,kruskal算法可以处理重边的情况,但是在处理的时候,不能仅仅因为两个节点在同一个连通子图就判断图不合法,只是不需要处理这条边,也就是不要加入并查集即可,重边也是一样。
所以只要判断图是否连通即可,但是也不能因为单单判断每个节点是否被访问过,因为就算全部被访问,还是可能不会连通。
只要判断加入并查集的边的条数是否等于n-1即可。上面都是自己开始做的没想清楚或者导致wa的,所以写下来作为自己的一点想法。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct edge { int u,v,cost; edge() {} edge(int x,int y,int z) { u=x; v=y; cost=z; } bool operator <(const edge& a) const { return cost>a.cost; } }; edge es[20010]; int par[1010]; int n,m; void init() { for(int i=1;i<=n;i++) par[i]=i; } int find(int x) { return x==par[x]?x:par[x]=find(par[x]); } void unite(int x,int y) { x=find(x); y=find(y); if(x!=y) par[x]=y; } long long kruskal() { sort(es,es+m); //for(int i=0;i<m;i++) printf("%d %d %d\n",es[i].u,es[i].v,es[i].cost); long long sum=0; int count=0; for(int i=0;i<m;i++) { edge e=es[i]; if(find(e.u)!=find(e.v)) { unite(e.u,e.v); count++; sum+=e.cost; } } if(count!=n-1) sum=-1; return sum; } int main() { //freopen("a.txt","r",stdin); int a,b,c; while(~scanf("%d%d",&n,&m)) { init(); for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); es[i]=edge(a,b,c); } printf("%lld\n",kruskal()); } return 0; }
http://poj.org/problem?id=2395
bessie打算去其他农场,这里总共有N个农场,她开始在1号农场,然后有M条双向连通的路,并且可能还有重边,所有的农场都至少有一条路和1号农场相连。去其他农场需要水所以需要一个水袋,但是不知道需要准备多大的袋子,已知每走一公里就会消耗一单元的水,并且每到一个农场就可以补充水,让你找出任意两个农场中距离最长的路,这样就能知道最少需要准备多大的袋子来装水。
扯了这么多 就是在最小生成树中找出路径最长的那一条边,比上面一题还简单。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct edge { int u,v,cost; edge() {} edge(int x,int y,int z) { u=x; v=y; cost=z; } bool operator <(const edge& a) const { return cost<a.cost; } }; edge es[10010]; int par[2010]; int n,m; void init() { for(int i=1;i<=n;i++) par[i]=i; } int find(int x) { return x==par[x]?x:par[x]=find(par[x]); } void unite(int x,int y) { x=find(x); y=find(y); if(x!=y) par[x]=y; } long long kruskal() { sort(es,es+m); //for(int i=0;i<m;i++) printf("%d %d %d\n",es[i].u,es[i].v,es[i].cost); long long sum=0; for(int i=0;i<m;i++) { edge e=es[i]; if(find(e.u)!=find(e.v)) { unite(e.u,e.v); if(e.cost>sum) sum=e.cost; } } return sum; } int main() { //freopen("a.txt","r",stdin); int a,b,c; while(~scanf("%d%d",&n,&m)) { init(); for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); es[i]=edge(a,b,c); } printf("%lld\n",kruskal()); } return 0; }
相关文章推荐
- POJ 2377 Bad Cowtractors【最小生成树变形&&最大生成树】
- POJ 1258 Agri-Net(最小生成树) && POJ 2377 Bad Cowtractors(最大生成树)
- POJ - 2377 Bad Cowtractors (最大生成树,Kruskal)
- POJ 2377 - Bad Cowtractors(最大生成树)
- POJ 2377 Bad Cowtractors(最大生成树)
- POJ 2377 Bad Cowtractors(最大生成树)
- poj 2377 Bad Cowtractors(最大生成树!)
- POJ 2377 Bad Cowtractors(最大生成树)
- POJ 2377 Bad Cowtractors(最大生成树,2016河南多校大一训练赛)
- Bad Cowtractors POJ - 2377(最大生成树)
- poj 2377 Bad Cowtractors(最大生成树)
- POJ 2377 Bad Cowtractors【最大生成树,Prime算法】
- POJ_2377_Bad Cowtractors_最大生成树
- POJ 2377 Bad Cowtractors(裸的最大生成树)
- poj 2377 Bad Cowtractors(最大生成树)
- POJ 2377 Bad Cowtractors【最大生成树】
- POJ 2377 Bad Cowtractors(kruskal最大生成树)
- poj 2377 Bad Cowtractors(最大生成树)
- POJ - 2377 Bad Cowtractors(最大生成树)
- POJ - 2377 Bad Cowtractors(图论/最大生成树)