NKOJ P2770 [USACO 2014 January Gold] 难度系数【最小生成树】

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;

const ll N=5e2+5;
const ll M=1e6+5;
const ll Inf=1e18;

ll n,m,t,id,tot,cnt,ans,f[M],num[M],num1[M],a[N][N],b[N][N],c[N][N];

struct node {
	ll x,y,z;
}line[M];

inline ll read() {
    ll x=0;char ch=getchar();bool f=0;
    while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?-x:x;
}

ll find(ll x) {
	return f[x]==x?x:f[x]=find(f[x]);
}

bool cmp(node p,node q) {
	return p.z<q.z;
}

void kruskal() {
	sort(line+1,line+1+cnt,cmp);
	
	rep(i,1,id) f[i]=i,num1[i]=1;
	
	for(ll i=1;i<=cnt&&tot;i++) {
		ll fx=find(line[i].x);
		ll fy=find(line[i].y);
		
		if(fx!=fy) {
			if(num1[fx]+num1[fy]>=t) {
				if(num1[fx]<t) {
					tot-=num[fx];
					ans+=num[fx]*line[i].z;
				}
				if(num1[fy]<t) {
					tot-=num[fy];
					ans+=num[fy]*line[i].z;
				}
 			}
			f[fx]=fy;
			num[fy]+=num[fx];
			num1[fy]+=num1[fx];
		}
	}
}

int main() {
	n=read(),m=read(),t=read();
	
	rep(i,1,n) rep(j,1,m) a[i][j]=read();
	
	rep(i,1,n) rep(j,1,m) {
		b[i][j]=read();
		c[i][j]=++id;num[id]=b[i][j];tot+=b[i][j];
	}

	rep(i,1,n) rep(j,1,m) {
		if(i!=n) {
			line[++cnt].x=c[i][j];
			line[cnt].y=c[i+1][j];line[cnt].z=abs(a[i][j]-a[i+1][j]);
		}
		if(j!=m) {
			line[++cnt].x=c[i][j];
			line[cnt].y=c[i][j+1];line[cnt].z=abs(a[i][j]-a[i][j+1]);
		}
	}
	
	kruskal();
	
	printf("%lld",ans);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/82778869
今日推荐