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