hdu 5934 強連通 && 判斷覆蓋圖的最少點


bomb  a 能觸發 b 則加一條a 到b 的邊。

用強連通縮點

處理DAG中每個點的最小代價。

覆蓋圖:所有出度爲0的點必須要被覆蓋,所有出度不爲0的點均可由其他點覆蓋。

所以 : 只要所有出度爲0的點, 就可以實現圖的覆蓋。


#include <bits/stdc++.h>

#define mod 1000000007
using namespace std ;
typedef long long ll ;
int ans[10050] ;

struct point {
    ll x , y , r , cost ;
    bool operator < ( const point & k ) const {
        return x < k.x ;
    }
};
point save[1050] ;
int par[1050] ;

int check(int x , int y){
    ll dis = (save[x].x - save[y].x)*(save[x].x - save[y].x) + (save[x].y - save[y].y)*(save[x].y - save[y].y) ;
    if(dis <= save[x].r*save[x].r) return x ;
    if(dis <= save[y].r*save[y].r) return y ;
    return -1 ;
}

const int MAX_V = 1005 ;
int V ; // point
vector <int> G[MAX_V] ;
vector <int> rG[MAX_V] ;
vector <int> vs ;///dui shou
bool used[MAX_V] ;
int cmp[MAX_V] ;

void add_edge( int from , int to ){
    G[from].push_back(to) ;
    rG[to].push_back(from) ;
}
void dfs( int v ){
    used[v] = true ;
    for( int i = 0 ; i < G[v].size() ; i ++ ){
        if( !used[ G[v][i] ])   dfs( G[v][i] ) ;
    }
    vs.push_back(v) ;
}
void rdfs( int v , int k ){
    used[v] = true ;
    cmp[v] = k ;
    for( int i = 0 ; i < rG[v].size() ; i ++ ){
        if( ! used[rG[v][i] ]) rdfs( rG[v][i] , k  );
    }
}
int scc(){
    memset(used , 0 ,sizeof( used)) ;
    vs.clear() ;
    for( int v = 1 ; v <= V ; v ++ ){
        if( !used[v]) dfs(v) ;
    }
    memset( used , 0 ,sizeof( used )) ;
    int k = 0  ;
    for( int i = vs.size() - 1 ; i >= 0 ; i -- ){
        if( ! used[ vs[i] ]) rdfs( vs[i] , k ++ ) ;
    }
    return k ;
}
map<int , ll> val ;
int deg[1050] ;
int main(){
    int T ; scanf("%d" , &T) ;
    int n , k ;
    int kk = 1 ;
    while(T --){
        scanf("%d" , &n) ;
        for( int i = 0 ; i <= n ; i ++ ) {
            G[i].clear() , rG[i].clear() ;
        }memset(cmp , 0 , sizeof( cmp)) ;
        V = n ;

        point tt ;
        for(int i = 1 ; i <= n ; i ++ ){
            scanf("%lld %lld %lld %lld" , &save[i].x , &save[i].y , &save[i].r , &save[i].cost) ;
        }

        for(int i = 1 ; i <= n ; i ++ ){
            for(int j = 1 ; j <= n ; j ++ ){
                if(i == j) continue ;
                if(check(i , j) == i){
                    add_edge(i , j) ;
                }else if(check(i , j) == j )
                    add_edge(j , i) ;
            }
        }
        int ans = scc() ;
        //cout << ans << endl ;
        val.clear() ;
        for(int i = 1 ; i <= n ; i ++ ){
            if(val.count(cmp[i]))
                val[ cmp[i] ] = min(val[ cmp[i] ] , save[i].cost) ;
            else
                val[ cmp[i] ] = save[i].cost ;
        }// cout << cmp[i ] << " " ;
        memset(deg , 0 , sizeof(deg)) ;
        for(int i = 1 ; i <= n ; i ++ ){
            for(int j = 0 ; j < G[i].size() ; j ++ ){
                //cout << i << " " << G[i][j] << endl ;
                if(cmp[ G[i][j] ] != cmp[i]){
                    deg[ cmp[ G[i][j] ] ] ++ ;
                }
            }
        }
        //for(int i = 0 ; i <= 5 ; i ++ ) cout << deg[i] << " " ; cout << endl ;
        ans = 0 ;
        for(int i = 1 ; i <= n ; i ++ ){
            if(!deg[ cmp[i] ]){
                ans += val[ cmp[i] ] ;
                deg[ cmp[i] ] ++ ;
            }
        }
        printf("Case #%d: %d\n" ,kk++ , ans ) ;
        //for(int i = 0 ; i < n ; i ++ ) cout << save[i].x << " " ;
    }
    return 0 ;
}

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