【E - Bomb】【HDU - 5934】【【基础班之强连通、桥、割顶专题训练】】【 WA 得清奇 】

                                             E - Bomb

传送门

【 解析 】

询问炸掉所有的炸弹的 cost ,那么

对于两个炸弹【 i,j 】 如果 i 爆炸后,可以让 j 也炸掉,那么就从 i 到 j 条边,表示 i (炸毁)则 j 可炸毁

                                      (这样 cost 会减少的嘛——免费炸毁 j )

即 i 到 j 的距离 小于等于 i 所能 炸到 的 范围 (半径 )

i 到 j 的距离 用公式 \large \mathit{​{​{\sqrt{(x_{1}-x_{2})^{2}-(y_{1}-y_{2})^{2}} <= dis}}}  

(如果防止精度问题,可以同时平方,实际上,这题不存在 -_- )

1 . 如果 A->B->A 那么A-B形成环,炸毁A、B中任意一个炸弹,都可同时毁掉 A && B ,那么

     我们 肯定 要选这个环里 最小的 点代价

2 . 解决 环 的情况之后,形成一个DAG(有向无环图)【 当然, 并 不 一定连通  】

     

3 . 显然可以得到:因为 1、2、3 号节点没有 别的节点 可以 帮忙 炸毁 它,所以他们一定要 自力更生

     ->  即一定 要 炸毁 (入度为 0 ) 的 它们

4 . 炸毁后:

      发现 : 别的节点 已经 KO 了!!!

So:炸毁入度为 0 的点即是最少的 cost 。

(PS:为什么不炸毁别的点呢,别的点已经 KO 啦,我干嘛要增加 cost 呢?)

【实际上,我当时并没有想到,我想的是DAG上的DP,然后,图不连通,这怎么搞?】

【然后,翻出了题解,原来如此啊,,我还是太菜了 】

【关于数据】

边最多有  \large \frac{n\times (n-1)}{2} 条( n是点数,单向边嘛)

真实数据中 没有 半径 < 0 的情况,担心的话 加个 特判好了

【 WA 的原因】

因为括号里先算,(LL)(int * int)这样的话里面算出来还是int,但是已经爆了,转化成 LL 也是没有用的

因而 WA 掉  (当然,你可用 sqrt )

所以这样写((LL)int * (LL)int) 才对,即使是(int * (LL)int)也是可以的啊,哭哭哭

至于 题面中 的  -1e8 < ri < 1e8  ,好像数据中是正常的,没有小于 0 的半径

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define LL long long
using namespace std;
const int inf = 0x7f7f7f7f;

inline int wread(){
	char c(getchar());int wans(0),flag(1);
	while (c<'0' ||c>'9'){if (c=='-')flag=-1;c=getchar ();}
	while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar();}
	return wans*=flag;
} 

struct node2{int xi,yi,ri,ci;}scf[1007];
int K,hed[1007];
struct node{int u,v,nxt;}e[1000007];
void ad (int u,int v){e[++K].v=v;e[K].nxt=hed[u];hed[u]=K;}
int dfn[1007],low[1007],cnt,SCC;
int S[1007],top;
bool ins[1007];
int belong_v[1007],eve[1007];
vector <int> T_SCC[1007];


void Tarjan_SCC(int x){
	dfn[x]=low[x]=++cnt;
	ins[x]=true;
	S[++top]=x;
	
	for (int i(hed[x]);i!=-1;i=e[i].nxt){
		int v(e[i].v);
		if (!dfn[v]){
			Tarjan_SCC(v);
			low[x]=min (low[x],low[v]);
		}
		else if (ins[v])	low[x]=min (low[x],dfn[v]);
	}
	
	if (dfn[x]==low[x]){
		SCC++;
		int y;
		do{
			y=S[top--];
			ins[y]=false;
			T_SCC[SCC].push_back(y);
			belong_v[y]=SCC;
		}while (x!=y);
	}
}

int num_v[1007];//统计每个SCC的入度 

void re_build(){
	
	for (int A(1);A<=SCC;++A){
		eve[A]=inf;
		for (int B(0); B<T_SCC[A].size(); ++B){
			int u(T_SCC[A][B]);
			eve[A]=min (eve[A], scf[u].ci);
			for (int i(hed[u]);i!=-1;i=e[i].nxt){
				int v(e[i].v);
				if (belong_v[v]==A)	continue;
				num_v[belong_v[v]]++;
			}
		}		
	}
	
}

int main (){
	
	int F(0);
	int T(wread());
	while (T--){
		F++;
		int n(wread());
		//初始化 
		for (int i(1);i<=n;++i)
			hed[i]=-1,dfn[i]=low[i]=ins[i]=num_v[i]=0,T_SCC[i].clear();
		K=cnt=top=SCC=0;
		
		//读入 
		for (int i(1);i<=n;++i)
			scf[i].xi=wread(),	scf[i].yi=wread(),	scf[i].ri=wread(), 	scf[i].ci=wread();
		//连边 
		for (int i=1;i<=n;++i)
			for (int j=1;j<=n;++j){
				if (i==j)	continue;
				LL ti1=((LL)scf[i].xi-(LL)scf[j].xi);
				ti1*=ti1;
				ti1+=((LL)scf[i].yi-(LL)scf[j].yi)*((LL)scf[i].yi-(LL)scf[j].yi);
				
				if (ti1<=((LL)scf[i].ri*(LL)scf[i].ri)) ad(i,j);
			}
		
		for (int i(1);i<=n;++i)
			if (!dfn[i])
				Tarjan_SCC(i);
		//统计新图入度为 0 的点  不需要重新建图 
		re_build();
		//统计答案 
		int ans(0);
		for (int i(1);i<=SCC;++i)
			if (num_v[i]==0)	ans+=eve[i];
		//输出 
		printf("Case #%d: %d\n",F,ans);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值