zoukankan      html  css  js  c++  java
  • HDU 5934 Bomb(tarjan/SCC缩点)题解

    思路:建一个有向图,指向能引爆对象,把强连通分量缩成一点,只要点燃图中入度为0的点即可。因为入度为0没人能引爆,不为0可以由别人引爆。

    思路很简单,但是早上写的一直错,改了半天了,推倒重来才过了...

    #include<cstdio>
    #include<set>
    #include<stack>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn = 1000+5;
    const int INF = 0x3f3f3f3f;
    int head[maxn],dfn[maxn],low[maxn],vis[maxn],in[maxn],scc[maxn],val[maxn];
    int tot,scc_int,index;
    stack<int> st;
    struct Edge{
        int u,v,next;
    }e[maxn*maxn];
    struct Node{
        ll x,y;
        ll r,c;
    }p[maxn];
    
    void addEdge(int u,int v){
        e[tot].u = u;
        e[tot].v = v;
        e[tot].next = head[u];
        head[u] = tot++;
    }
    
    void tarjan(int u){
        vis[u] = 1;
        dfn[u] = low[u] = ++index;
        st.push(u);
        for(int i = head[u];i != -1;i = e[i].next){
            int v = e[i].v;
            if(!dfn[v]){
                tarjan(v);
                low[u] = min(low[u],low[v]);
            }
            else if(vis[v]){
                low[u] = min(low[u],dfn[v]);
            }
        }
        if(dfn[u] == low[u]){
            scc_int++;
            ll MIN = INF;
            int v;
            do{
                v = st.top();
                st.pop();
                vis[v] = 0;
                scc[v] = scc_int;
                MIN = min(MIN,p[v].c);
            }while(v != u);
            val[scc_int] = MIN;
        }
    }
    void init(){
        tot = scc_int = index = 0;
        while(!st.empty()) st.pop();
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(vis,0,sizeof(vis));
        memset(in,0,sizeof(in));
    }
    int main(){
        int T,n,Case = 1;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            init();
            for(int i = 1;i <= n;i++)
                scanf("%lld%lld%lld%lld",&p[i].x,&p[i].y,&p[i].r,&p[i].c);
            for(int i = 1;i <= n;i++){
                for(int j = i + 1;j <= n;j++){
                    ll dis = (p[i].x - p[j].x)*(p[i].x - p[j].x) + (p[i].y - p[j].y)*(p[i].y - p[j].y);
                    if(p[i].r*p[i].r >= dis){
                        addEdge(i,j);
                    }
                    if(p[j].r*p[j].r >= dis){
                        addEdge(j,i);
                    }
                }
            }
            for(int i = 1;i <= n;i++){
                if(!dfn[i])
                    tarjan(i);
            }
            for(int i = 1; i<= n;i++){
                for(int j = head[i];~j;j = e[j].next){
                    int v = e[j].v;
                    if(scc[i] != scc[v]){
                        in[scc[v]]++;
                    }
                }
            }
            ll ans = 0;
            for(int i = 1;i <= scc_int;i++){
                if(in[i] == 0){
                    ans += val[i];
                }
            }
            printf("Case #%d: %lld
    ",Case++,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    MyBatis:分页的实现
    Mybatis之配置文件
    Java之创建线程的方式四:使用线程池
    Java之创建线程的方式三:实现Callable接口
    Java之线程通信的应用:经典例题:生产者/消费者问题
    Java之线程通信的方法
    Java之解决线程安全问题的方式三:Lock锁
    Java之同步方法处理实现Runnable接口的线程安全问题
    Java之同步方法处理继承Thread类的线程安全问题
    01 while 循环输入1 2 3 4 5 6 8 9 10
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9408738.html
Copyright © 2011-2022 走看看