#并查集,Kruskal,01背包#

并查集

洛谷 1536 村村通

求还要修多少条路,也就是问集合的数量-1。

#include 
using namespace std;
int f[1001],n,m,x,y;
int getf(int u){return (f[u]==u)?u:f[u]=getf(f[u]);}
void uni(int x,int y){
    int fa=getf(x),fb=getf(y);
    if (fa!=fb) f[fb]=fa;
}
int main(){
    while (scanf("%d%d",&n,&m)==2){
        for (int i=1;i<=n;i++) f[i]=i; int ans=0;
        for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),uni(x,y);
        for (int i=1;i<=n;i++) if (f[i]==i) ans++;
        printf("%d\n",ans-1);
    } return 0;
} 

洛谷 2256 一中校运会之百米跑

并查集改字符串,其实也没什么。

#include 
#include 
using namespace std;
int n,m; string x,y;
map<string,string>uk;
string getf(string u){return (uk[u]==u)?u:uk[u]=getf(uk[u]);}
void uni(string x,string y){
	string fa=getf(x),fb=getf(y);
	if (fa!=fb) uk[fb]=fa;
}
int main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for (int i=1;i<=n;i++) cin>>x,uk[x]=x;
	for (int i=1;i<=m;i++) cin>>x>>y,uni(x,y); cin>>n;
	for (int i=1;i<=n;i++){
		cin>>x>>y;
		if (getf(x)!=getf(y)) cout<<"No."<<endl; else cout<<"Yes."<<endl;
	} return 0;
} 

洛谷 1111 修复公路

Kruskal

#include 
#include 
using namespace std;
struct z{int x,y,k;}a[100001]; 
int n,m,f[1001],total,ans;
int getf(int u){return (f[u]==u)?u:f[u]=getf(f[u]);}
bool cmp(z p,z q){return p.k<q.k;}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) f[i]=i;
	for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].k);
	stable_sort(a+1,a+1+m,cmp);
	for (int i=1;i<=m;i++){
		if (getf(a[i].x)!=getf(a[i].y)){
			f[getf(a[i].y)]=getf(a[i].x);
			total++;
			ans=a[i].k;
		}
		if (total==n-1) break;
	}
	if (total!=n-1) ans=-1;
	printf("%d",ans); return 0;
} 

洛谷 1455 搭配购买

并查集+01背包

状态转移方程: f [ j ] = m a x ( f [ j ] , f [ j − w [ i ] ] + v [ i ] ) f[j]=max(f[j],f[j-w[i]]+v[i]) f[j]=max(f[j],f[jw[i]]+v[i])

#include
#include
using namespace std;
int n,m,a,b,A,B,g,w[10001],v[10001],fa[10001],f[20000001];
int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}
int main()
{
    scanf("%d%d%d",&n,&m,&g);
    for (int i=1;i<=n;i++)scanf("%d%d",w+i,v+i),fa[i]=i;
    for (int i=1;i<=m;i++){
	    scanf("%d%d",&a,&b);
        if((A=getf(a))==(B=getf(b))) continue;
        fa[B]=A;v[A]+=v[B];w[A]+=w[B];
	}
    for (int i=1;i<=n;i++)if(fa[i]==i){
    for (int j=g;j>=w[i];j--)
	f[j]=max(f[j],f[j-w[i]]+v[i]);}
    printf("%d",f[g]);return 0;
}

你可能感兴趣的:(背包,并查集,最小生成树)