hdu5934 Tarjan 缩点

Bomb

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 95    Accepted Submission(s): 46


Problem Description
There are  N bombs needing exploding.

Each bomb has three attributes: exploding radius  ri, position  (xi,yi) and lighting-cost  ci which means you need to pay  ci 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.
 

Input
First line contains an integer  T, which indicates the number of test cases.

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

In the following  N lines, the ith line contains four intergers  xi yi ri and  ci, indicating the coordinate of ith bomb is  (xi,yi), exploding radius is  ri and lighting-cost is  ci.

Limits
1T20
1N1000
108xi,yi,ri108
1ci104
 

Output
For 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
 

Source
2016年中国大学生程序设计竞赛(杭州)

题意:有n个炸弹,每个炸弹有三个属性,位置,爆炸半径,手动爆炸花费,如果A爆炸,在A的爆炸范围内的炸弹都会爆炸,问使所有炸弹爆炸
最小花费是多少;

如果A能引爆B,那么在A B之间建一条单向边A->B ,然后用Tarjan算法缩点,缩点过程把相连通分量内的那个花费最小的炸弹求出并保存,然后用缩点建立新图,每次引爆入度为0的炸弹即可, 
如何建立新图?u->v, belong[u]!=belong[v],说明u v不在同一个分量里,那么 belong[u]->belong[v]建立新边,在此题中不必真正的建立新图,只要求入度就好了,
AC代码:
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int maxn=1005;
struct node
{
    LL x,y,r;
    int c;
} d[maxn];
struct Edge
{
    int to,next;
} edge[maxn*maxn*2];
int tot,head[maxn];
int vis[maxn],in[maxn];
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
LL D(int i,int j)
{
    return (d[i].x-d[j].x)*(d[i].x-d[j].x)+(d[i].y-d[j].y)*(d[i].y-d[j].y);
}
int num[maxn];///每个联通分量含有点的个数
int g[maxn],f[maxn];///f入度,g出度
int dfn[maxn],low[maxn],v[maxn],s[maxn],b[maxn];
int n,cnt=0,times,t;
int c[maxn];
void Tarjan(int x)
{
    int y,i;
    times++;
    t++;
    dfn[x]=low[x]=times;
    v[x]=1;
    s[t]=x;
    for (i=head[x]; i!=-1; i=edge[i].next)
    {
        y=edge[i].to;
        if (v[y]==0)
        {
            Tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        if (v[y]==1)
            low[x]=min(low[x],dfn[y]);
    }
    if (dfn[x]==low[x])
    {
        cnt++;
        do
        {
            y=s[t--];
            c[cnt]=min(c[cnt],d[y].c);///保存cnt 分量里的最小花费
            b[y]=cnt;///属于哪个强连通分量
            v[y]=2;

        }
        while (y!=x);
    }
}
LL solve(int n)
{
    times=0;
    t=0;
    cnt=0;///连通分量个数
    memset(dfn,0,sizeof(dfn));
    memset(v,0,sizeof(v));
    memset(c,inf,sizeof(c));
    for(int i=0; i=temp)
                add(i,j);

                if(d[j].r*d[j].r>=temp)
                add(j,i);
            }
        }
        LL ans=solve(n);
        printf("Case #%d: %d\n",cas,ans);
    }
    return 0;
}


你可能感兴趣的:(-------连通图)