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


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