BZOJ4410: [Usaco2016 Feb]Fence in
偶尔来道奶牛题休闲一下。
$a \leq 1e9$,$b \leq 1e9$,$a*b$的大矩形中有$n \leq 25000$条竖栏杆$m \leq 25000$条横栏杆(a对n,b对m),这些栏杆是无限长的且互不重合。给竖栏杆的横坐标和横栏杆的纵坐标。现在这些栏杆把矩形隔成很多块,问移除最短多长的子栏杆使得所有小矩形连通。如下图。
------>
用最小生成树的想法,贪心选最小的来割。于是两边栏杆排个序,一个一个加答案即可。
具体这么割:比如你要割横的(注意这里的横的是n竖的是m)
一开始切两组(不如说颜色)蓝的:
然后要切一组红的。虽然之前切了蓝的,但这两条蓝的行还没连通,因此还是要切2条:
现在又要切条红的。注意,现在那两条蓝行的已经连通,因此可以少切一条:
诸如此类,分一下是不是第一次切这个方向(颜色)的边即可,如果不是就可以减掉另一方向已经连通的数量。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<vector> 6 //#include<queue> 7 //#include<time.h> 8 //#include<complex> 9 #include<algorithm> 10 #include<stdlib.h> 11 using namespace std; 12 13 int n,m,A,B; 14 #define maxn 25011 15 int a[maxn],b[maxn]; 16 #define LL long long 17 int main() 18 { 19 scanf("%d%d%d%d",&A,&B,&n,&m); 20 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 21 sort(a+1,a+1+n); 22 a[n+1]=A-a[n]; for (int i=n;i;i--) a[i]=a[i]-a[i-1]; n++; 23 for (int i=1;i<=m;i++) scanf("%d",&b[i]); 24 sort(b+1,b+1+m); 25 b[m+1]=B-b[m]; for (int i=m;i;i--) b[i]=b[i]-b[i-1]; m++; 26 27 sort(a+1,a+1+n); 28 sort(b+1,b+1+m); 29 int p=1,q=1; 30 LL ans=0; 31 a[n+1]=b[m+1]=0x3f3f3f3f; 32 while (p<=n || q<=m) 33 if (a[p]<b[q]) ans+=1ll*a[p]*(m-1-(p>1)*(q==1?0:q-2)),p++; 34 else ans+=1ll*b[q]*(n-1-(q>1)*(p==1?0:p-2)),q++; 35 printf("%lld\n",ans); 36 return 0; 37 }