最小生成树kruskal_征兵

来源:互联网 发布:网络推广神器 编辑:程序博客网 时间:2024/05/01 16:04
XX 有一个国家,他要建立一个军队来保护他的国家,现在他选出了 n 个男孩和 m 个女
孩,准备将这些人征召来当兵,正常情况下,每增加一个士兵要花费 10000 元,但是在一
些男孩和女孩之间存在一些关系,我们可以利用这些关系来减少成本。如果女孩 x 和男孩 y 关系强度为 d ,如果其中一个已经在军队中那么另外一人加到军队里面 只需要花费
(10000-d)元 (这里保证 0<=d<10000). 现在给你所有男女孩之间的关系,请你求出最
少的花费。
注意:每次征兵最多只能使用一个关系。如:女孩 1 和男孩 1 有关系 d1,女孩 1 和男
孩 2 有关系 d2, 那么你只能使用 d1 或者 d2。 ★数据输入
第一行有三个整数 n,m,R(1<=n<=10000,1<=m<=10000, 0<=R<=50000),表示男孩个
数,女孩个数,还有关系数。 接下来 R 行,每行有三个整数 x 和 y,d(0<=x<n,
0<=y<m,0<=d<10000),表示图 G 的一组关系。 ★数据输出

输出最小花费。输入示例




5 5 8
4 3 6831
1 3 4583
0 0 6592
0 1 3063
3 3 4975
1 3 2049
4 2 2104
2 2 781


71071



1.求最小花费,就是想办法用尽可能少的花费证入人,也就是有关系找关系,没关系就花费10000

那么 ans=有关系的人的最小生成树+没关系的人的钱


2..为方便区别男女,本程序将会:男的编号=男的原来编号+女的总人数,以此来区别男女   

如:女编号:0~~~girls-1   男编号girls~~girls+boys-1  那么编号就会一一对应一个人


3.为得到最小花费,将输入数据的关系值改成花费 转化关系为  花费=10000-关系值



4.问题关键在于怎么 转化,,可以一个人看做一个点,人之间的关系值转化成花费,那么人之间的花费就可以看做点之间边的权值

把可以联系在一起的点联系在一起,利用kruskal算法得到最小值



             #include<cstdio>#include<algorithm>const int N=50010;using namespace std;struct node{    int s,e;    int w;};node G[N];int parent[2*N/5];int find(int e){    int i,j=e;    while(parent[j]!=j)j=parent[j];    while(j!=e)    {        i=parent[e];        parent[e]=j;        e=i;    }    return j;}bool cmp(const node &a,const node &b){return a.w>b.w;}int kruskal(int edge){    int ans=0,i;    for(i=0;i<2*N/5;++i) parent[i]=i;    for(i=0;i<edge;++i)    {        int a=find(G[i].s),b=find(G[i].e);        if(a!=b)        {          //  printf("a:%d b:%d\n",a,b);            ans+=G[i].w;            parent[a]=b;        }    }    return ans;}int main(){    int i,n,m,r;    scanf("%d %d %d",&n,&m,&r);    for(i=0;i<r;++i){        scanf("%d %d %d",&G[i].s,&G[i].e,&G[i].w);        G[i].e+=n;    }    sort(G,G+r,cmp);    printf("%d\n",10000*(n+m)-kruskal(r));}        





0 0
原创粉丝点击