zoukankan      html  css  js  c++  java
  • hdu1827 强连通

    题意:一个人需要联系其他所有人,已知他自己联系每个人的花费,并且他可以联系某个人再让他联系他能联系到的人,给出一系列关系表示 A 能够联系 B。问他最少需要联系多少人,花费多少钱

    首先,建成一个有向图,强连通分量内的点可以相互通知,但是如果某个强连通分量入度为0,那么这个强连通分量中的点不能通过其他分量到达,因此只要通知这些入度为0的强连通分量中花费最少的一个人就行了,所以强连通时更新每个分量的最小花费值,然后建边记录入度,联系人数就是入度为0的强连通分量数,而花费就是这些分量的最小花费和。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stack>
     4 #include<queue>
     5 using namespace std;
     6 
     7 const int maxn=1005;
     8 const int maxm=2005;
     9 
    10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
    11 int n,t,scccnt;
    12 int stx[maxn],low[maxn],scc[maxn],num[maxn],a[maxn],id[maxn],ans1,ans2;
    13 stack<int>S;
    14 
    15 void init(){
    16     memset(head,-1,sizeof(head));
    17     size[0]=size[1]=0;
    18     ans1=ans2=0;
    19 }
    20 
    21 void add(int a,int b,int c=0){
    22     point[c][size[c]]=b;
    23     nxt[c][size[c]]=head[c][a];
    24     head[c][a]=size[c]++;
    25     if(c)id[b]++;
    26 }
    27 
    28 void dfs(int s){
    29     stx[s]=low[s]=++t;
    30     S.push(s);
    31     for(int i=head[0][s];~i;i=nxt[0][i]){
    32         int j=point[0][i];
    33         if(!stx[j]){
    34             dfs(j);
    35             low[s]=min(low[s],low[j]);
    36         }
    37         else if(!scc[j]){
    38             low[s]=min(low[s],stx[j]);
    39         }
    40     }
    41     if(low[s]==stx[s]){
    42         scccnt++;
    43         while(1){
    44             int u=S.top();S.pop();
    45             scc[u]=scccnt;
    46             if(a[u]<num[scccnt])num[scccnt]=a[u];
    47             if(s==u)break;
    48         }
    49     }
    50 }
    51 
    52 void setscc(){
    53     memset(stx,0,sizeof(stx));
    54     memset(scc,0,sizeof(scc));
    55     memset(num,0x3f,sizeof(num));
    56     memset(id,0,sizeof(id));
    57     t=scccnt=0;
    58     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
    59     for(int i=1;i<=n;++i){
    60         for(int j=head[0][i];~j;j=nxt[0][j]){
    61             int k=point[0][j];
    62             if(scc[i]!=scc[k]){
    63                 add(scc[i],scc[k],1);
    64             }
    65         }
    66     }
    67 }
    68 
    69 int main(){
    70     int m;
    71     while(scanf("%d%d",&n,&m)!=EOF){
    72         init();
    73         for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    74         while(m--){
    75             int a,b;
    76             scanf("%d%d",&a,&b);
    77             add(a,b);
    78         }
    79         setscc();
    80         for(int i=1;i<=scccnt;++i){
    81             if(!id[i]){ans1++;ans2+=num[i];}
    82         }
    83         printf("%d %d
    ",ans1,ans2);
    84     }
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    springboot: 使web项目支持jsp
    springboot: 集成freemark模板引擎
    Springboot的优点和实现
    Spring的两种动态代理:Jdk和Cglib 的区别和实现
    JAVA单例模式:懒汉式,饿汉式
    java的内存管理 对象的分配与释放
    JAVA反射调用方法
    JAVA内置注解 基本注解
    图——图的定义与操作
    树——二叉树的线索化
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4799351.html
Copyright © 2011-2022 走看看