Bomb
下午模拟了一波ccpc杭州站,结果崩的不行,C题被卡精度,这题一眼过去以为是费用流,结果在费用流的道路上一去不复返。为什么费用流不行呢,因为无法在边上赋边权,每条边被经过多次,可能会多次统计,然后各种改,最后发现没法解决。
也是加强了对网络流的理解吧。
赛后结束队友惊呼是强连通缩点。。。。
因为写流的时候用到了bitset传递闭包,索性用bitset传递闭包,然后用并查集缩点,只需统计入度为0的联通块中的点权最小值之和即可。
const int N=1e3+10;
struct node
{
double x,y,r;
int cost;
} a[N];
int cnt[N],f[N],vis[N],ru[N];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
bitset<1001>b[1001];
int main()
{
int t,n;
scanf("%d",&t);
int t1=t;
while(t--)
{
scanf("%d",&n);
memset(vis,0,sizeof(vis));
memset(ru,0,sizeof(ru));
for(int i=1; i<=n; i++) scanf("%lf%lf%lf%d",&a[i].x,&a[i].y,&a[i].r,&a[i].cost),a[i].r*=a[i].r;
for(int i=1; i<=n; i++)
{
b[i].reset();
f[i]=i,cnt[i]=INF;
for(int j=1; j<=n; j++)
if(i!=j)
{
double dis=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
if(dis<=a[i].r)
b[i][j]=1;
}
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) if(b[j][i]) b[j]|=b[i];
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if(b[i][j]==1&&b[j][i]==1)
{
int f1=find(i),f2=find(j);
f[f1]=f2;
}
for(int i=1; i<=n; i++) //统计每个分量的最值
{
int ff=find(i);
cnt[ff]=min(cnt[ff],a[i].cost);
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if(b[i][j])
{
int f1=find(i),f2=find(j);
if(f1!=f2) ru[f2]++;
}
ll ans=0;
for(int i=1; i<=n; i++)
{
int ff=find(i);
if(ru[ff]==0)
{
ans+=cnt[ff];
cnt[ff]=0;
}
}
printf("Case #%d: %lld\n",t1-t,ans);
}
return 0;
}