Bomb HDU - 5934 强联通图,连通分量tarjan算法(模板)

There are NN bombs needing exploding. 

Each bomb has three attributes: exploding radius riri, position (xi,yi)(xi,yi) and lighting-cost cici which means you need to pay cici cost making it explode. 

If a un-lighting bomb is in or on the border the exploding area of another exploding one, the un-lighting bomb also will explode. 

Now you know the attributes of all bombs, please use the minimum cost to explode all bombs.
InputFirst line contains an integer TT, which indicates the number of test cases. 

Every test case begins with an integers NN, which indicates the numbers of bombs. 

In the following NN lines, the ith line contains four intergers xixiyiyiriri and cici, indicating the coordinate of ith bomb is (xi,yi)(xi,yi), exploding radius is riri and lighting-cost is cici

Limits 
1T201≤T≤20 
1N10001≤N≤1000 
108xi,yi,ri108−108≤xi,yi,ri≤108 
1ci1041≤ci≤104OutputFor every test case, you should output 'Case #x: y', where x indicates the case number and counts from 1 and y is the minimum cost.Sample Input
1
5
0 0 1 5
1 1 1 6
0 1 1 7
3 0 2 10
5 0 1 4
Sample Output

Case #1: 15

代码:

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
#define LL long long
#define N 2000

class Bomb                          //数据
{
public:
    long long x,y,r,c;
}bo[1050];

int n;                             //点的个数
stack<int>sta;                // 存储已遍历的结点
vector<int>gra[N];            // 邻接表表示图
int dfn[N];                 // 深度优先搜索访问次序
int low[N];                 // 能追溯到的最早的次序
int InStack[N];             // 检查是否在栈中(2为在栈中,1为已访问,且不在栈中,0为不在)
vector<int> Component[N];     // 获得强连通分量结果
int InComponent[N];         // 记录每个点在第几号强连通分量里
int index,ComponentNumber;  // 索引号,强连通分量个数
LL cost[N];                // 缩点后每个缩点的最小花费
int rudu[N];                //入度,此题入度为0的点是必须点燃的Bomb

void Pre_Processing()
{
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(InStack,0,sizeof(InStack));
    memset(InComponent,0,sizeof(InComponent));
    memset(rudu,0,sizeof(rudu));
    memset(cost,0x3f3f3f3f,sizeof(cost));
    index=ComponentNumber=0;
    for(int i=0;i<=n;i++)
    {
        gra[i].clear();
        Component[i].clear();
    }
    while(!sta.empty())
    {
        sta.pop();
    }
}
bool judge(LL x1,LL y1,LL x2,LL y2,LL r1)
{
    if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<=r1*r1)
        return true;
    else
        return false;
}
void input()
{
      cin>>n;
      Pre_Processing();
      for(int i=1;i<=n;i++)
      {
          cin>>bo[i].x>>bo[i].y>>bo[i].r>>bo[i].c;
      }
      for(int i=1;i<n;i++)
      {
          for(int j=i+1;j<=n;j++)
            {
                if(judge(bo[i].x,bo[i].y,bo[j].x,bo[j].y,bo[i].r)) gra[i].push_back(j);
                if(judge(bo[i].x,bo[i].y,bo[j].x,bo[j].y,bo[j].r)) gra[j].push_back(i);
            }
      }
}
void tarjan(int u)
{
    InStack[u]=2;
    dfn[u]=low[u]=++index;
    sta.push(u);
    for(int i=0;i<gra[u].size();i++)
    {
        int t=gra[u][i];
        if(dfn[t]==0)
        {
            tarjan(t);
            low[u]=min(low[t],low[u]);
        }
        else if(InStack[t]==2)
        {
            low[u]=min(low[u],dfn[t]);
        }
    }
    if(low[u]==dfn[u])
    {
        ++ComponentNumber;
        while(!sta.empty())
        {
            int j=sta.top();
            sta.pop();
            InStack[j]=1;
            Component[ComponentNumber].push_back(j);
            InComponent[j]=ComponentNumber;
            cost[ComponentNumber]=min(bo[j].c,cost[ComponentNumber]);//记录每个缩点的最小花费
            if(j==u)
            {
                break;
            }
        }
    }
}

int solve()
{
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        {
            tarjan(i);
        }
    }
    for(int i=1;i<=n;i++)//找出缩点后的入度
    {
        for(int j=0;j<gra[i].size();j++)
        {
            int q=gra[i][j];
            if(InComponent[i]!=InComponent[q])
            rudu[InComponent[q]]++;
        }
    }
    int ans=0;
    for(int i=1;i<=ComponentNumber;i++)
    {
        if(rudu[i]==0)
        {
            ans=cost[i]+ans;
        }
    }
    return ans;
}
int main()
{
  int T;
  cin>>T;
  for(int t=1;t<=T;t++)
  {
    input();
    cout<<"Case #"<<t<<": "<<solve()<<endl;
  }
   return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章