最小生成树

例题一:http://acm.hdu.edu.cn/showproblem.php?pid=1879

AC代码:

#include<iostream>//c++
#include<cmath>//数学公式
#include<cstdlib>//malloc
#include<cstring>
#include<string>
#include<cstdio>//输入输出
#include<algorithm>//快排
#include<queue>//队列
#include<functional>//优先队列
#include<stack>//栈
#include<vector>//容器
#include<map>//地图  if continue
typedef long long ll;
const  int N=10+100;
const  int inf=0x7fffffff;
using namespace std;
int w[N],n;
typedef struct{
	int a,b,c;
}G;G g;
struct cmp{
	bool operator() (G x ,G y)
	{
	  return x.c>y.c;
  	}
};
priority_queue<G ,vector<G> ,cmp >q;
void liantong(int a,int b)
{
	int c=w[a];
	for(int i=1;i<=n;i++)
		if(c==w[i]) w[i]=w[b]; 
}
int main()
{
    //freopen("C:\\Users\\ch\\Desktop\\1.txt","r",stdin);
	//freopen("C:\\Users\\lenovo\\Desktop\\2.txt","w",stdout);
	int i,j,k;
	int a,b,c,d;
	while(scanf("%d",&n),n)
	{
		while(!q.empty())	q.pop();
	    int m=n-1;
	    int ans=0;
	    for(i=1;i<=n;i++)	w[i]=i;
	    for(i=0;i<(n-1)*n/2;i++)
	    {
	    	scanf("%d%d%d%d",&a,&b,&c,&d);
	    	if(d)	liantong(a,b),--m;
			else {g.a=a;g.b=b;g.c=c;q.push(g);}
		}
		while(m>0)
		{
			g=q.top();
			q.pop();
			if(w[g.a]==w[g.b]) continue;
			ans+=g.c;
			liantong(g.a,g.b);
			m--;
		}
//		cout<<ans<<endl;
		printf("%d\n",ans);
	}
	return 0;
}

例题二:http://acm.hdu.edu.cn/showproblem.php?pid=1863

AC代码:

#include<iostream>//c++
#include<cmath>//数学公式
#include<cstdlib>//malloc
#include<cstring>
#include<string>
#include<cstdio>//输入输出
#include<algorithm>//快排
#include<queue>//队列
#include<functional>//优先队列
#include<stack>//栈
#include<vector>//容器
#include<map>//地图  if continue
typedef long long ll;
const  int N=10+100;
const  int inf=0x7fffffff;
using namespace std;
int w[N],n;
typedef struct{
	int a,b,c;
}G;G g;
struct cmp{
	bool operator() (G x ,G y)
	{
	  return x.c>y.c;
  	}
};
priority_queue<G ,vector<G> ,cmp >q;
void liantong(int a,int b)
{
	int c=w[a];
	for(int i=1;i<=n;i++)
		if(c==w[i]) w[i]=w[b]; 
}
int main()
{
    //freopen("C:\\Users\\ch\\Desktop\\1.txt","r",stdin);
	//freopen("C:\\Users\\lenovo\\Desktop\\2.txt","w",stdout);
	int i,j,k;
	int a,b,c,d;
	while(scanf("%d%d",&d,&n),d)
	{
		while(!q.empty())	q.pop();
	    int m=n-1;
	    int ans=0;
	    for(i=1;i<=n;i++)	w[i]=i;
	    for(i=0;i<d;i++)
	    {
	    	scanf("%d%d%d",&g.a,&g.b,&g.c);
	    	q.push(g);
		}
		while(m>0&&!q.empty())
		{
			g=q.top();
			q.pop();
			if(w[g.a]==w[g.b]) continue;
			ans+=g.c;
			liantong(g.a,g.b);
			m--;
		}
		if(m>0)	 printf("?\n");
		else     printf("%d\n",ans);
	}
	return 0;
}

http://acm.fzu.edu.cn/problem.php?pid=2087

(有多少边至少存在一个最小生成树里面)

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn=100005;
const int maxm=100005;
int n,m;
int parent[maxn];

struct Node
{
    int from,to,w;
}node[maxm];

void init(int n)
{
    for(int i=1;i<=n;i++)
        parent[i]=i;
}

int find(int x)
{
    if(parent[x]==x)
        return x;
    else
        return parent[x]=find(parent[x]);
}

bool same(int x,int y)
{
    return find(x)==find(y);
}
void unite(int x,int y)
{
    parent[find(x)]=find(y);
}

bool cmp(Node a,Node b)
{
    return a.w<b.w;
}

void solve()
{
    int cnt=0;
    int i,j;
    for(i=1;i<=m;i=j)
    {
        for(j=i;node[j].w==node[i].w;j++)//只要相同权值的边两个端点不在同一个集合,该边就一定存在一个最小生成树里面
        {
            if(!same(node[j].from,node[j].to))
                cnt++;
        }
        for(j=i;node[j].w==node[i].w;j++)//有回路的边加上不影响后面的加边
            unite(node[j].from,node[j].to);
    }
    printf("%d\n",cnt);
}

int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init(n);
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&node[i].from,&node[i].to,&node[i].w);
        sort(node+1,node+1+m,cmp);
        solve();
    }
    return 0;
}



你可能感兴趣的:(最小生成树,ACM,HDU)