hdu 3072

强连通分量——tarjin 算法

这道题和前面那道hdu 2767唯一不同就是,2767需要找出最小数量的边使图成为连通分量,而这个题需要一点点贪心的思想在里面,它需要求出代价最小的边使图成为连通分量;

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <stack>
 5 #define N 50006
 6 using namespace std;
 7 
 8 struct Edge
 9 {
10     int u, val, next;
11     Edge() {}
12     Edge(int a, int b, int c)
13     {
14         u=a, val=b, next=c;
15     }
16 } edge[100006];
17 
18 int head[N],tot,n,m,dfn[N],low[N],T,ind,id[N],in[N];
19 bool vs[N];
20 stack<int> S;
21 
22 void add_edge(int st, int en, int val)
23 {
24     edge[tot]=Edge(en,val,head[st]);
25     head[st]=tot++;
26 }
27 
28 void tarjan(int u)
29 {
30     S.push(u), vs[u]=true;
31     dfn[u]=low[u]=T++;
32     for(int e=head[u]; e!=-1; e=edge[e].next)
33     {
34         int v=edge[e].u;
35         if(!dfn[v])
36         {
37             tarjan(v);
38             low[u]=min(low[u], low[v]);
39         }
40         else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v];
41     }
42     if(low[u]==dfn[u])
43     {
44         ind++;
45         int v;
46         do
47         {
48             v=S.top();
49             S.pop();
50             id[v]=ind;
51             vs[v]=false;
52         }while(v!=u);
53     }
54 }
55 
56 int main()
57 {
58     while(scanf("%d%d", &n, &m)!=EOF)
59     {
60         memset(head, -1, sizeof head);
61         tot=0;
62         for(int i=0, a, b, c; i<m; i++)
63         {
64             scanf("%d%d%d", &a, &b, &c);
65             add_edge(a,b,c);
66         }
67         while(!S.empty()) S.pop();
68         memset(vs, 0, sizeof vs);
69         memset(dfn,0, sizeof dfn);
70         memset(low,0,sizeof low);
71         T=ind=0;
72         for(int i=0; i<n; i++) if(!dfn[i]) tarjan(i);
73         for(int i=0; i<ind; i++) in[i]=999999;
74         for(int i=0; i<n; i++)
75         {
76             int u=id[i];
77             for(int e=head[i]; e!=-1; e=edge[e].next)
78             {
79                 int v=id[edge[e].u];
80                 if(u!=v) in[v]=min(in[v], edge[e].val);
81             }
82         }
83         int ans=0;
84         for(int i=0; i<ind; i++)
85         {
86             if(i==id[0]||in[i]==999999) continue;
87             ans+=in[i];
88         }
89         printf("%d\n", ans);
90     }
91     return 0;
92 }
View Code

 

posted @ 2013-09-04 20:12  Yours1103  阅读(362)  评论(0编辑  收藏  举报