hdu 1827(强联通缩点建图)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1827

思路:缩点后建新图,然后找入度为0的点,在入度为0的点中找颜色相同的最小的花费,将这些花费相加就是最后最小的花费了。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<vector>

 6 #include<stack>

 7 using namespace std;

 8 #define MAXN 1111

 9 #define inf 1<<30

10 vector<int>vet[MAXN];

11 vector<int>map[MAXN];

12 stack<int>S;

13 bool mark[MAXN];

14 int color[MAXN];

15 int to[MAXN];//入度

16 int dfn[MAXN],low[MAXN];

17 int n,m,cnt,_count;

18 int cost[MAXN];

19 

20 void Tarjan(int u){

21    dfn[u]=low[u]=++cnt;

22    mark[u]=true;

23    S.push(u);

24    for(int i=0;i<vet[u].size();i++){

25       int v=vet[u][i];

26       if(dfn[v]==0){

27          Tarjan(v);

28          low[u]=min(low[u],low[v]);

29       }else if(mark[v]){

30          low[u]=min(low[u],dfn[v]);

31       }

32    }

33    if(low[u]==dfn[u]){

34       int v;

35       _count++;

36       do{

37          v=S.top();

38          S.pop();

39          mark[v]=false;

40          color[v]=_count;

41       }while(u!=v);

42    }

43 }

44 

45 int Solve(int u){

46    int MIN=inf;

47    for(int i=1;i<=n;i++){

48       if(color[i]==u&&cost[i]<MIN){

49          MIN=cost[i];

50       }

51    }

52    return MIN;

53 }

54 

55 

56 int main(){

57  //  freopen("1.txt","r",stdin);

58    int u,v,ans,count;

59    while(~scanf("%d%d",&n,&m)){

60       for(int i=1;i<=n;i++){ vet[i].clear();map[i].clear(); }

61       for(int i=1;i<=n;i++)scanf("%d",&cost[i]);

62       for(int i=1;i<=m;i++){

63          scanf("%d%d",&u,&v);

64          vet[u].push_back(v);

65       }

66       memset(mark,false,sizeof(mark));

67       memset(dfn,0,sizeof(dfn));

68       memset(low,0,sizeof(low));

69       memset(color,0,sizeof(color));

70       memset(to,0,sizeof(to));

71       _count=cnt=0;

72       for(int i=1;i<=n;i++){

73          if(dfn[i]==0)Tarjan(i);

74       }

75       for(int i=1;i<=n;i++){

76          for(int j=0;j<vet[i].size();j++){

77             if(color[i]!=color[vet[i][j]]){

78                map[color[i]].push_back(color[vet[i][j]]);

79                to[color[vet[i][j]]]++;

80             }

81          }

82       }

83       count=ans=0;

84       for(int i=1;i<=_count;i++){

85          if(to[i]==0){

86             count++;

87             ans+=Solve(i);

88          }

89       }

90       printf("%d %d\n",count,ans);

91    }

92    return 0;

93 }
View Code

 

你可能感兴趣的:(HDU)