hdu 1827 Summer Holiday

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=1827

用tarjan算法,先对各个极大强连通图进行缩点同时记录缩点中话费最少的值,然后看每一个缩点的入度,如果入度为0,那么说明需要给这个缩点打电话。

源代码:

 1 #include <iostream>
 2 #include<vector>
 3 #include<stdio.h>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define INF 100000000
 7 using namespace std;
 8 vector<int> map[20005];
 9 
10 int n,m,now,cnt,sum1,sum2,top,num,ans;
11 int dfn[20005],low[20005],stack[20005],Stack[20005],belong[20005],to[20005],c[10005];
12 int mini[10005];
13 void tarjan(int a){
14   dfn[a]=low[a]=++now;
15   int u;
16   stack[++top]=a;  //如果用标准库中自带的stack会超时~~~,用这个数组模拟栈
17   Stack[a]=1;     //注意我用大写Stack表示是否在栈中,小写s模拟栈
18   for(int i=0;i<map[a].size();i++){
19     u=map[a][i];
20     if(!dfn[u]){
21       tarjan(u);
22       low[a]=min(low[a],low[u]);
23     }
24     else if(Stack[u])
25       low[a]=min(low[a],dfn[u]);
26   }
27     if(low[a]==dfn[a]){
28         int temp;
29         cnt++;
30       do{
31          temp=stack[top--];
32          belong[temp]=cnt;
33          if(c[temp]<mini[cnt])
34             mini[cnt]=c[temp];
35         Stack[temp]=0;
36       }while(temp!=a);
37     }
38   }
39   
40  void fun(){
41    for(int i=1;i<=n;i++){
42      for(int j=0;j<map[i].size();j++){
43          int k=map[i][j];
44      if(belong[i]!=belong[k]){ //相邻两个点不属于同一缩点
45          to[belong[k]]++;
46        }
47      }
48    }
49    for(int i=1;i<=cnt;i++){
50      if(!to[i]){     //入度为0
51        ans+=mini[i];
52        num++;}
53    }
54    return;
55  }
56 
57 int main()
58 {
59   while(scanf("%d %d",&n,&m)!=EOF){
60 
61       cnt=now=sum1=sum2=0;
62       top=ans=0;
63       num=0;
64       memset(dfn,0,sizeof(dfn)); //时间戳
65       memset(low,0,sizeof(low)); //极大强连通图的最小时间
66       memset(Stack,0,sizeof(Stack)); //是否在栈中
67       memset(to,0,sizeof(to)); //缩点的入度
68       for(int i=1;i<=n;i++){
69           scanf("%d",&c[i]); //每个点的话费
70         map[i].clear();    //这个一定要写啊,我老是忘了写这个
71         mini[i]=INF;       //每个缩点的最小话费
72       }
73           for(int i=1;i<=m;i++){
74             int a,b;
75             scanf("%d %d",&a,&b);
76             map[a].push_back(b);
77           }
78     for(int i=1;i<=n;i++){
79       if(!dfn[i])
80         tarjan(i);
81     }
82     fun();
83     printf("%d %d\n",num,ans);
84   }
85     return 0;
86 }

 

posted @ 2013-08-20 11:00  小の泽  阅读(154)  评论(0编辑  收藏  举报