HDU ACM 1827 Summer Holiday(图的强连通+缩点)

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

思路:用Tarjan算法求出各个强连通分支,同一个强连通分支抽象成一点

  1 #include <iostream>
  2 #include <vector>
  3 #include <stack>
  4 using namespace std;
  5 const int maxn = 1000 + 10;
  6 const int maxm = 2000 + 10;
  7 struct Node{
  8     int cost;
  9     int dfn;
 10     int low;
 11     int belong;
 12 };
 13 Node Call[maxn];
 14 vector <int> v[maxn];
 15 stack <int> s;
 16 int time;
 17 int instack[maxn];
 18 int indegree[maxn];
 19 void Tarjan(int u){
 20     Call[u].dfn = Call[u].low = ++time;
 21     s.push(u);
 22     instack[u] = 1;
 23     int i;
 24     for(i=0;i<v[u].size();i++){
 25         if(Call[v[u][i]].dfn == 0){
 26             Tarjan(v[u][i]);
 27             Call[u].low = min(Call[u].low,Call[v[u][i]].low);
 28         }
 29         else{
 30             if(instack[v[u][i]]){
 31                 Call[u].low = min(Call[u].low,Call[v[u][i]].dfn);
 32             }
 33         }
 34     }
 35     if(Call[u].low == Call[u].dfn){
 36         int x = s.top();
 37         s.pop();
 38         instack[x] = 0;
 39         Call[x].belong = u;
 40         Call[u].cost = min(Call[u].cost,Call[x].cost);
 41         while(x != u){
 42             x = s.top();
 43             s.pop();
 44             instack[x] = 0;
 45             Call[x].belong = u;
 46             Call[u].cost = min(Call[u].cost,Call[x].cost);
 47         }
 48     }
 49 }
 50 void Init(){
 51     while(!s.empty()){
 52         s.pop();
 53     }
 54     int i;
 55     for(i=0;i<maxn;i++){
 56         v[i].clear();
 57     }
 58     memset(Call,0,sizeof(Call));
 59     memset(instack,0,sizeof(instack));
 60     memset(indegree,0,sizeof(indegree));
 61 }
 62 int main(){
 63     int n,m;
 64     while(cin>>n>>m){
 65         Init();
 66         int i,j;
 67         for(i=1;i<=n;i++){
 68             cin>>Call[i].cost;
 69         }
 70         int a,b;
 71         for(i=1;i<=m;i++){
 72             scanf("%d%d",&a,&b);
 73             v[a].push_back(b);
 74         }
 75         time = 0;
 76         for(i=1;i<=n;i++){
 77             if(!Call[i].dfn){
 78                 Tarjan(i);
 79             }
 80         }
 81         int used[maxn] = {0};
 82         for(i=1;i<=n;i++){
 83             for(j=0;j<v[i].size();j++){
 84                 if(Call[i].belong != Call[v[i][j]].belong){
 85                     indegree[Call[v[i][j]].belong]++;
 86                 }
 87             }
 88         }
 89         int sum = 0;
 90         int num = 0;
 91         for(i=1;i<=n;i++){
 92             if(!used[Call[i].belong] && indegree[Call[i].belong] == 0 ){
 93                 used[Call[i].belong] = 1;
 94                 sum++;
 95                 num += Call[Call[i].belong].cost;
 96             }
 97         }
 98         cout<<sum<<" "<<num<<endl;
 99     }
100     return 0;
101 }
102 /*
103 Sample Input
104 12 16
105 2 2 2 2 2 2 2 2 2 2 2 2 
106 1 3
107 3 2
108 2 1
109 3 4
110 2 4
111 3 5
112 5 4
113 4 6
114 6 4
115 7 4
116 7 12
117 7 8
118 8 7
119 8 9
120 10 9
121 11 10
122 Sample Output
123 3 6
124 */

 

posted @ 2013-03-25 11:54  zx雄  阅读(220)  评论(0编辑  收藏  举报