hdu 3861 The King’s Problem 强连通+二分匹配
来源:互联网 发布:js移动轨迹 编辑:程序博客网 时间:2024/05/19 02:21
#include<stdio.h>#include<string.h>#include<algorithm>#include<stack>#include<vector>#define maxn 5005#define maxm 100005#define clr(a,b) memset(a,b,sizeof(a))using namespace std;stack<int>s;vector<int>vc[maxn];int ca,n,m,bcnt,e,first[maxn],ev[maxm],next[maxm],index;int dfn[maxn],low[maxn],belong[maxn],x[maxm],y[maxm],mat[maxn];int instack[maxn],vis[maxn];void tarjan(int u){ int v; dfn[u]=low[u]=++index; s.push(u); instack[u]=1; for(int i=first[u];i!=-1;i=next[i]) { v=ev[i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { bcnt++; do{ v=s.top(); belong[v]=bcnt; instack[v]=0; s.pop(); }while(v!=u); }}bool find(int u){ int v; for(int e=0;e<vc[u].size();e++) { v=vc[u][e]; if(vis[v]) continue; vis[v]=1; if(mat[v]==-1||find(mat[v])) { mat[v]=u; return 1; } } return 0;}int Hungary(int nx){ int Max=0; clr(mat,-1); for(int i=1;i<=nx;i++) { clr(vis,0); if(find(i)) Max++; } return Max;}void add(int u,int v){ next[e]=first[u],ev[e]=v,first[u]=e++;}void init(){ clr(first,-1); e=1; bcnt=0; index=0; clr(dfn,0); clr(low,0); clr(instack,0); clr(belong,0); while(!s.empty()) s.pop();}int main(){ //freopen("D:/d.txt","r",stdin); scanf("%d",&ca); while(ca--) { init(); scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d %d",&x[i],&y[i]); add(x[i],y[i]); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); if(bcnt==1) { puts("1"); continue; } for(int i=0;i<=bcnt;i++) vc[i].clear(); for(int i=1;i<=m;i++) { int u=belong[x[i]]; int v=belong[y[i]]; if(u!=v) vc[u].push_back(v); } printf("%d\n",bcnt-Hungary(bcnt)); } return 0;}