题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5934
题面
题意
题目是说有个炸弹,每个炸弹有其对应的坐标(,)、爆炸半径以及引爆其所需的费用,当一个炸弹爆炸时在其爆炸半径内其它未爆炸的炸弹也会爆炸。问使所有炸弹爆炸的最小费用是多少。
思路
显然我们可以把炸弹之间的引爆关系看成有向边(因为存在爆炸半径,所以A可以引爆B不一定B可以引爆A)把炸弹看成图中的点,问题就转化成了,图中有个点以及若干条有向边,选取第个点的费用是,问选取若干个点使得图中每个点都可到达所需的最小费用是多少?
有向图中可能存在强连通分量,考虑每个强连通分量的最小代价必然是强连通分量中代价最小的点,我们可以将每个强连通分量用其中代价最小的点代替,再重新建图,这时若存在A指向B的关系,显然B就可以不用选了。
故完整算法就是:
- 读入所有点的数据,暴力建图
- 找强连通分量,把所有强连通分量的代价用其中代价最小的点代替
- 重新建图
- 找出所有入度为0的点,把代价加起来即得答案。
顺便吐槽一下HDOJ越界了居然返回TLE
AC代码
#include<stdio.h>
#include<stack>
#include<algorithm>
typedef long long LL;
using namespace std;
stack<int>sta;
int head[1005],c[1005],nxt[3005050],p[3005050],vis[1005],dfn[1005],low[1005],f[1005];
int rd[1005],mi[1005];
int t,cot,n,cnt,Case=0,ans=0;
LL x[1005],y[1005],r[1005];
void dfs(int now)
{
sta.push(now);
for(int i=head[now];i;i=nxt[i])
{
if(vis[p[i]]!=t)
{
vis[p[i]]=t;dfn[p[i]]=low[p[i]]=dfn[now]+1;
dfs(p[i]);
low[now]=min(low[now],low[p[i]]);
}else
if(!f[p[i]]) low[now]=min(low[now],low[p[i]]);
}
if(dfn[now]==low[now])
{
++cot;
while(sta.top()!=now)
{
f[sta.top()]=cot;
sta.pop();
}
f[sta.top()]=cot;
sta.pop();
}
return;
}
int main()
{
scanf("%d",&t);
while(t)
{
Case++;
for(int i=1;i<=n;i++)head[i]=0,f[i]=0,dfn[i]=0,low[i]=0;
for(int i=1;i<=cot;i++)rd[i]=0,mi[i]=0;
cnt=0;cot=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld%d",&x[i],&y[i],&r[i],&c[i]);
}
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
{
if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])<=r[i]*r[i])
{
p[++cnt]=j;nxt[cnt]=head[i];head[i]=cnt;
}
if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])<=r[j]*r[j])
{
p[++cnt]=i;nxt[cnt]=head[j];head[j]=cnt;
}
}
for(int i=1;i<=n;i++)
if(vis[i]!=t)
{
vis[i]=t;
dfn[i]=1;low[i]=1;
dfs(i);
}
//找所有强连通分量
for(int i=1;i<=n;i++)
{
if((!mi[f[i]])||mi[f[i]]>c[i])mi[f[i]]=c[i];
for(int j=head[i];j;j=nxt[j])
if(f[i]!=f[p[j]])
{
rd[f[p[j]]]++;
}
}//以找到的强联通分量重新建图,计算入度
ans=0;
for(int i=1;i<=cot;i++)if(!rd[i])ans+=mi[i];
printf("Case #%d: %d\n",Case,ans);
t--;
}
return 0;
}
来源:https://blog.csdn.net/weixin_44582673/article/details/99676235