zoukankan      html  css  js  c++  java
  • HDU5934 强连通分量

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5934

    1. 根据距离关系建边
    2. 对于强连通分量来说,只需引爆话费最小的炸弹即可引爆整个强连通分量
    3. 将所有的强连通分量缩成点,我们就得到了一棵树,我们只需要引爆树根的炸弹即可
    4. 我们可以处理出每个点所属的强连通分量的拓扑序,或者说染色法,把属于同一个强连通分量的点标上同一个数字
    5. 处理完强连通分量后,我们不需要建树,我们可以用并查集来维护,更好的办法是统计每个点的入度,入读为0即为根节点
       1 #include<bits/stdc++.h>
       2 using namespace std;
       3 typedef long long ll;
       4 const int maxv = 1111;
       5 int V;//总共点的个数 
       6 vector<int> g[maxv];
       7 vector<int> rg[maxv];
       8 vector<int> vs;
       9 bool used[maxv];
      10 int cmp[maxv];//保存拓扑序 
      11 ll cost[maxv];//每个拓扑序的话费 
      12 ll x[1111],y[1111],r[1111],c[1111];
      13 ////scc
      14 void dfs(int v){
      15     used[v] = true;
      16     for(int i = 0;i<g[v].size();i++)
      17         if(!used[g[v][i]])
      18             dfs(g[v][i]);
      19     vs.push_back(v);
      20 }
      21 void rdfs(int v,int k){
      22     used[v] = true;
      23     cmp[v] = k;
      24     cost[k] = min(cost[k],c[v]);//处理出每个强连通分量的最小话费 
      25     for(int i = 0;i<rg[v].size();i++)
      26         if(!used[rg[v][i]])
      27             rdfs(rg[v][i],k);
      28 }
      29 int scc(){
      30     memset(used,0,sizeof(used));
      31     vs.clear();
      32     for(int v = 1;v<=V;v++)//这里要注意,下标是从0开始还是从1开始 
      33         if(!used[v])
      34             dfs(v);
      35     memset(used,0,sizeof(used));
      36     int k = 1;
      37     for(int i = vs.size()-1;i>=0;i--)
      38         if(!used[vs[i]])
      39             rdfs(vs[i],k++);
      40     return k;
      41 }
      42 //////
      43 void addedge(int i,int j){
      44     ll dis = (y[i]-y[j])*(y[i]-y[j])+(x[i]-x[j])*(x[i]-x[j]);
      45     if(dis <= r[i]*r[i]){
      46         g[i].push_back(j);
      47         rg[j].push_back(i);    
      48     }
      49     if(dis <= r[j]*r[j]){
      50         g[j].push_back(i);
      51         rg[i].push_back(j);
      52     }
      53 }
      54 //////
      55 int du[1111];
      56 int main(){
      57     int t;
      58     cin >> t;
      59     int cas = 1;
      60     while(t--){
      61         int n;
      62         cin >> n;
      63         V = n;
      64         memset(cost,0x3f3f3f3f,sizeof(cost));
      65         for(int i = 1;i<=n;i++){
      66             g[i].clear();
      67             rg[i].clear();
      68         }
      69         for(int i = 1;i<=n;i++){
      70             scanf("%I64d%I64d%I64d%I64d",&x[i],&y[i],&r[i],&c[i]);
      71             for(int j = 1;j<i;j++){
      72                 addedge(i,j);
      73             }
      74         }
      75         int k = scc();
      76         memset(du,0,sizeof(du));
      77         for(int i = 1;i<=n;i++)
      78             for(int j = 0;j<g[i].size();j++)
      79                 if(cmp[i] != cmp[g[i][j]])//拓扑序不同,度数加1 
      80                     du[cmp[g[i][j]]]++;
      81         ll ans = 0;
      82         for(int i = 1;i<k;i++)
      83             if(du[i] == 0)
      84                 ans += cost[i] ;
      85         printf("Case #%d: %I64d
      ",cas++,ans);
      86     }
      87     return 0;
      88 }
  • 相关阅读:
    iOS Graphics 编程
    如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1
    Python服务器开发二:Python网络基础
    Access一些问题
    托管调试助手报错
    ConnectionString
    百度也开源
    Microsoft SQL Server 错误代号: 15535 解决方法
    临时表的一个用法
    类型初始值设定项引发异常
  • 原文地址:https://www.cnblogs.com/zqy123/p/6020009.html
Copyright © 2011-2022 走看看