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

来源:互联网 发布:基本款斜挎包 知乎 编辑:程序博客网 时间:2024/05/19 00:16

题目链接: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

 

 

0 0
原创粉丝点击