HDU-5934 Bomb 缩点

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值