hdu5934(tarjan缩点)

来源:互联网 发布:linux 命令输出到变量 编辑:程序博客网 时间:2024/06/06 01:11

题意:给出一些炸弹,引爆需要花费一些价值,引爆炸弹会有一个爆炸范围,在爆炸范围之内的炸弹也会被引爆。求出包所有的炸弹引爆的最小价值。

思路:有炸弹在一个炸弹的爆炸范围之内就说明这个炸弹能引爆其他炸弹,说明要建的是有向图。

  现在这个有向图可能出现环或者一些复杂的情况,所以需要tarjan缩点,使其成为一个简单的DAG,引爆联通块中的任何一个点,这个联通块中所有的点就会被引爆,这样的话判断是否是入度为0的联通块,再将它加入答案之中。联通块的引爆代价为它的所有点的最小代价。


PS:写着写着,发现以前的tarjan板子有点小毛病,调了好久,现在改过来了。


#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int> P;#define clr(x,y) memset(x,y,sizeof x)#define INF 0x3f3f3f3fconst int maxn = 1000 + 10;struct Node{ll x,y,r;int w;}a[maxn];struct Edge{    Edge(){}    Edge(int x,int y):to(x),next(y){}    int to,next;}edge[maxn * maxn];int edge_num;int is_(Node c1,Node c2){    ll d = (c1.x - c2.x) * (c1.x - c2.x) + (c1.y - c2.y) * (c1.y - c2.y),R1 = c1.r * c1.r ,R2 = c2.r * c2.r;    if(d <= R1 && d <= R2)        return 1;    if(d <= R1)        return 2;    if(d <= R2)        return 3;    return 4;}int head[maxn];bool vis[maxn];int stacks[maxn];int dfn[maxn],low[maxn];int col[maxn];int top;int cnt;int cost[maxn];P b[maxn * maxn];void Init(){    cnt = 0;    edge_num = 0;    clr(head,-1);    clr(vis,false);    clr(dfn,0);    clr(low,0);    clr(col,0);}void add_edge(int x,int y){    edge[edge_num] = Edge(y,head[x]);head[x] = edge_num ++;}void tarjan(int u,int &len){    dfn[u] = low[u] = len;    vis[u] = true;stacks[++ top] = u;    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].to;        if(!dfn[v])        {            len ++;            tarjan(v,len);            low[u] = min(low[u],low[v]);        }        else if(vis[v])low[u] = min(low[u],dfn[v]);    }    if(dfn[u] == low[u])    {        col[u] = ++cnt;//        cout << cnt << " :  " << u ;        cost[cnt] = a[u].w;        vis[u] = false;        while(stacks[top --] != u)        {            int val = stacks[top + 1];//            cout <<"    "<< val << " ";            cost[cnt] = min(cost[cnt],a[val].w);            col[val] = cnt;            vis[val] = false;        }//        cout << endl;    }}int main(){    int Tcase;    scanf("%d",&Tcase);    for(int ii = 1; ii <= Tcase;ii ++)    {        Init();        int n;        scanf("%d",&n);        for(int i = 1; i <= n; i ++)        {            scanf("%I64d%I64d%I64d%d",&a[i].x,&a[i].y,&a[i].r,&a[i].w);        }        int lens = 0;        for(int i = 1; i <= n; i ++)        {            for(int j = i + 1; j <= n; j ++)            {                int temp = is_(a[i],a[j]);                if(temp == 1)                {//                    cout << i << " < - > " << j  << endl;                    add_edge(i,j);add_edge(j,i);                    b[lens ++] = P(i,j);b[lens ++] = P(j,i);                }                else if(temp == 2){                    add_edge(i,j),b[lens ++] = P(i,j);//                    cout << i <<" -> " << j << endl;                }                else if(temp == 3){                    add_edge(j,i),b[lens ++] = P(j,i);//                    cout << j << " -> " << i << endl;                }            }        }        top = 0;        for(int i = 1; i <= n; i ++)        {            if(!dfn[i])            {                int len = 1;                tarjan(i,len);            }        }        int in[maxn];        clr(in,0);        for(int i = 0; i < lens; i ++)        {            int x = col[b[i].first],y = col[b[i].second];            if(x != y)in[y] ++;        }        int ans = 0;        for(int i = 1; i <= cnt; i ++)        {//            cout << i << " " <<in[i]  << " " << cost[i] <<  endl;            if(!in[i])                ans += cost[i];        }        printf("Case #%d: %d\n",ii,ans);    }    return 0;}


原创粉丝点击