HDU-5934-scc

http://acm.hdu.edu.cn/showproblem.php?pid=5934

题目大意:

有n个炸弹,给出他们的坐标(x,y)以及伤害半径r和引爆代价c。

在炸弹爆炸半径以内以及边缘上的炸弹会被连锁引爆。求最少需要多少的代价引爆所有的炸弹。  

思路:

求scc缩点,然后产生若干个DAG,找到每个DAG得起点,对每个起点内的所有点找一个最小的代价点贡献给ans,累加求解就是答案,

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pii pair<int,int>
 4 #define mp make_pair
 5 const int maxn=1005;
 6 int T,N;
 7 long long x[maxn],y[maxn],r[maxn],c[maxn];
 8 vector<int>g[maxn];
 9 int sum,scc_cnt;
10 int low[maxn],dfn[maxn],scc[maxn],in[maxn];
11 stack<int>S;
12 bool ok(int i,int j){
13     return (y[i]-y[j])*(y[i]-y[j])+(x[i]-x[j])*(x[i]-x[j])<=r[i]*r[i];
14 }
15 void dfs(int u){
16     low[u]=dfn[u]=++sum;
17     S.push(u);
18     for(int v:g[u]){
19         if(!dfn[v]){
20             dfs(v);
21             low[u]=min(low[u],low[v]);
22         }else if(!scc[v]) low[u]=min(low[u],dfn[v]);
23     }
24     if(low[u]==dfn[u]){
25         ++scc_cnt;
26         int x=-1;
27         while(x!=u){
28             x=S.top();
29             S.pop();
30             scc[x]=scc_cnt;
31         }
32     }
33 }
34 int main(){ 
35     scanf("%d",&T);
36     for(int cas=1;cas<=T;++cas){
37         cin>>N;
38         sum=scc_cnt=0;
39         while(!S.empty())S.pop();
40         for(int i=1;i<=N;++i)
41         low[i]=dfn[i]=scc[i]=0,
42         g[i].clear(),scanf("%lld%lld%lld%lld",&x[i],&y[i],&r[i],&c[i]);
43         for(int i=1;i<=N;++i){
44             for(int j=1;j<=N;++j){
45                 if(i==j)continue;
46                 if(ok(i,j))g[i].push_back(j);
47             }
48         }
49         for(int i=1;i<=N;++i){
50             if(!dfn[i])dfs(i);
51         }//puts("---");
52         for(int i=1;i<=scc_cnt;++i)in[i]=0;
53         for(int i=1;i<=N;++i){
54             for(int j:g[i]){
55                 if(scc[i]==scc[j])continue;
56                 in[scc[j]]++;
57             }
58         }
59         long long ans=0;
60         for(int i=1;i<=scc_cnt;++i){
61             if(in[i]==0){
62                 long long minc=99999999;
63                 for(int j=1;j<=N;++j){
64                     if(scc[j]==i){
65                         minc=min(minc,c[j]);
66                     }
67                 }
68                 ans+=minc;
69             }
70         }
71         cout<<"Case #"<<cas<<": "<<ans<<endl;
72     }
73     return 0;
74 }

 

-

posted @ 2020-01-08 20:07  *zzq  阅读(263)  评论(0编辑  收藏  举报