hdu 3861(缩点+最小路径覆盖)

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

思路:缩点是显然的:What’s more, for each pair of city (u, v), if there is one way to go from u to v and go from v to u, (u, v) have to belong to a same state.然后就是建新图了,求最大匹配即可。

这里有最小路径覆盖==|顶点个数|-最大匹配;

 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 5555

 9 vector<int>vet[MAXN];//原图

10 vector<int>map[MAXN];//缩点后的图

11 stack<int>S;

12 bool mark[MAXN];//标记元素是否在栈中

13 int color[MAXN];//缩点,染色

14 int n,m,cnt,_count;

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

16 int lx[MAXN],ly[MAXN];

17 bool visited[MAXN];

18 

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       //没访问过

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

28          Tarjan(v);

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

30       }else if(mark[v]){ low[u]=min(low[u],dfn[v]); }

31    }

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

33       int v;

34       do{

35          v=S.top();

36          S.pop();

37          mark[v]=false;

38          color[v]=_count;//缩点,染色

39       }while(u!=v);

40       _count++;

41    }

42 }

43 

44 

45 int dfs(int u){

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

47       int v=map[u][i];

48       if(!visited[v]){

49          visited[v]=true;

50          if(ly[v]==-1||dfs(ly[v])){ ly[v]=u;lx[u]=v;return 1; }

51       }

52    }

53    return 0;

54 }

55 

56 

57 int MaxMatch(){

58    int res=0;

59    memset(lx,-1,sizeof(lx));

60    memset(ly,-1,sizeof(ly));

61    for(int i=0;i<_count;i++){

62       memset(visited,false,sizeof(visited));

63       if(lx[i]==-1)res+=dfs(i);

64    }

65    return res;

66 }

67 

68 int main(){

69    int _case,u,v;

70    scanf("%d",&_case);

71    while(_case--){

72       scanf("%d%d",&n,&m);

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

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

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

76          vet[u].push_back(v);

77       }

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

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

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

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

82       _count=cnt=0;

83       for(int i=1;i<=n;i++)if(dfn[i]==0)Tarjan(i);

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

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

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

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

88             }

89          }

90       }

91       int ans=MaxMatch();

92       printf("%d\n",_count-ans);

93    }

94    return 0;

95 }
View Code

 

 

你可能感兴趣的:(HDU)