您的位置:首页 > 其它

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的,所以写下来作为自己的一点想法。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: