第一题(diyiti.cpp/c/pas)
【Description】
农村已整改,套路深似海啊..
W村要想上网,一共有n个家庭,家所在位置可以用(x,y)的坐标表示出来
一个家庭上网可以通过下面两种方式上网:
1)直接连上网络,需要付出A的代价
2)蹭别人的网,和一家可以上网的家庭py,需要付出B*两地曼哈顿距离的代价
请问W村所有家庭都能上网的最小代价
【Input】
第一行三个整数n、A、B,意义如题
第二行到第n+1行,每行两个整数,代表xi、yi,意义如题
【Output】
一个整数,代表最小代价
【Sample Input】
5 10 2
0 0
0 1
1 0
1 1
100 100
【Sample Output】
26
【Data】
对于30%的数据 n<=3 A<=50 B<=5
对于60%的数据 n<=100 A<=1000 B<=20
对于100%的数据 n<=10^3 A<=10^4 B<=50 |xi|、|yi|<=2^15
【Tips】
定义两点曼哈顿距离为|Xi-Xj|+|Yi-Yj|
这题一开始以为是网络流,于是想了半天。。
于是没想出来。。
于是就想贪心随便弄弄
大概就是距离代价小于等于A的连下边。。
然后就出现了很多个连通块
很明显,每一个连通块只有一个地方连A就好了,然后剩下就是一个最小生成树。。
于是就AC了
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
typedef long long LL;
using namespace std;
const LL N=1005;
LL X[N],Y[N];
LL n,A,B;
struct qq
{
LL x,y,last,z;
}s[N*N];LL num,last[N];
void init (LL x,LL y)
{
num++;
s[num].x=x;s[num].y=y;
s[num].last=last[x];
last[x]=num;
return ;
}
bool vis[N];
bool in[N];
void dfs (LL x)
{
if (in[x]) return ;
vis[x]=true;in[x]=true;
for (LL u=last[x];u!=-1;u=s[u].last)
{
LL y=s[u].y;
dfs(y);
}
}
qq e[N*N];LL num1;
void init1 (LL x,LL y,LL z)
{
num1++;
e[num1].x=x;e[num1].y=y;e[num1].z=z;
}
LL f[N];
bool cmp (qq a,qq b){return a.z<b.z;}
LL find (LL x){return f[x]==x?f[x]:f[x]=find(f[x]);}
LL dis (LL x,LL y)
{
return abs(X[x]-X[y])+abs(Y[x]-Y[y]);
}
LL ans=0;
void lalal ()
{
num1=0;
for (LL u=1;u<=n;u++)
{
if (in[u]==false) continue;
for (LL i=u+1;i<=n;i++)
if (in[i]==true)
init1(u,i,B*dis(u,i));
}
/* for (LL u=1;u<=n;u++)
if (in[u])
printf("%lld ",u);*/
for (LL u=1;u<=n;u++) f[u]=u;
sort(e+1,e+1+num1,cmp);
// for (LL u=1;u<=num1;u++) printf("%lld %lld %lld\n",e[u].x,e[u].y,e[u].z);
for (LL u=1;u<=num1;u++)
{
LL x=e[u].x,y=e[u].y;
LL fx=find(x),fy=find(y);
if (fx==fy) continue;
f[fx]=fy;
ans=ans+e[u].z;
}
ans=ans+A;
}
int main()
{
freopen("diyiti.in","r",stdin);
freopen("diyiti.out","w",stdout);
num=0;memset(last,-1,sizeof(last));
scanf("%lld%lld%lld",&n,&A,&B);
for (LL u=1;u<=n;u++) scanf("%lld%lld",&X[u],&Y[u]);
for (LL u=1;u<=n;u++)
for (LL i=u+1;i<=n;i++)
if (B*dis(u,i)<=A)
{
init(u,i),init(i,u);
}
memset(vis,false,sizeof(vis));
for (LL u=1;u<=n;u++)
{
memset(in,false,sizeof(in));
if (vis[u]==true) continue;
dfs(u);
lalal();
}
printf("%lld\n",ans);
return 0;
}