hdu 5934(强连通缩点)

Bomb

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


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

题意:二维平面上有 n 个炸弹,每个炸弹有个引爆的代价和爆炸半径,问至少花费多少代价才能引爆所有炸弹。炸弹爆炸的时候会引爆半径及内所有炸弹。


解:构造,将一个炸弹引爆另一条边的过程变成一条有向边。炸弹就是点。所以,那些入度为0的点就是必须要引爆的点(无炸弹将其引爆)。由此构图,强连通分量缩点,使得整张图无连通,求出所有入度为0的权值即可(一个强连通分量可以与一个点等价,其权值为内部最小的权值)。


代码:

#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1005;
const int maxm = maxn*maxn;
const int inf =999999;
struct node{
    int v,u,next;
}edge[ maxm ];
int head[ maxn ],cnt;
int vis[ maxn ],low[ maxn ],dfn[ maxn ],id;
int n,m,ans1;
int cost[ maxn ];
int belong[ maxn ],inde[ maxn ];//缩点,入度
int X[maxn],Y[maxn],R[maxn];
stackq;
void init(){
    cnt=0;
    id=0;
    ans1=0;
    memset( vis,0,sizeof( vis ));
    memset( dfn,-1,sizeof(dfn) );
    memset( low,-1,sizeof( low ));
    memset( head,-1,sizeof( head ));
}
void addedge( int a,int b ){
    edge[ cnt ].v=a;
    edge[ cnt ].u=b;
    edge[ cnt ].next=head[ a ];
    head[ a ]=cnt++;
}
void tarjan( int now ){
    dfn[ now ]=low[ now ]=id++;
    vis[ now ]=1;
    q.push( now );
    for( int i=head[ now ];i!=-1;i=edge[ i ].next ){
        int next=edge[ i ].u;
        if( dfn[ next ]==-1 ){
            tarjan( next );
            low[ now ]=min( low[ now ],low[ next ]);
        }
        else if( vis[ next ]==1 ){
            low[ now ]=min( low[ now ],dfn[ next ] );
        }
    }
    if( low[ now ]==dfn[ now ] ){
        ans1++;
        while( 1 ){
            int tmp;
            tmp=q.top(),q.pop();
            vis[ tmp ]=0;
            belong[ tmp ]=ans1;
            if( tmp==now ) break;
        }
    }
}

int main(){
    int t,T=0;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&X[i],&Y[i],&R[i],&cost[i]);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j) continue;
                long long now=1LL*(X[j]-X[i])*(X[j]-X[i])+1LL*(Y[j]-Y[i])*(Y[j]-Y[i]);
                if(now<=1LL*R[i]*R[i])
                    addedge(i,j);
            }
        }
        while( !q.empty() ) q.pop();
        for( int i=1;i<=n;i++ ){
            if( dfn[ i ]==-1 ){
                tarjan( i );
            }
        }
        int a,b;
        memset( inde,0,sizeof( inde ));
        for( int i=0;i






你可能感兴趣的:(图论)