题意:给你n个城市,每个城市之间有一条有向边,将城市划分为几个区域,问你最小的划分方法,
划分规则为:能相互到达的放在一个区域;然后区域内的a,b两点肯定存在某种方式,使得a能到b或者b能到a(注意,这里没说一定是相互能到);
解题思路:这道题其实就是DAG上的对应二分图的最小路径覆盖;
因为DAG,所以先缩点,然后对应二分图的最小路径覆盖=顶点数-对应二分图的最大匹配;
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> #define N 5005 #define M 100005 using namespace std; struct node { int x; int y; }a[M]; struct Edge { int next; int to; }edge[M]; int ans=0; int match[M]; int head[M]; int instack[M]; int visit[M]; int low[M]; int dfn[M]; int sccno[M]; int book[M]; int cnt; int step; int index; int scc_cnt; bool e[N][N]; int n,m; vector<int>scc[N]; void add(int u,int v) { edge[cnt].next=head[u]; edge[cnt].to=v; head[u]=cnt++; } void tarjan(int u) { low[u]=dfn[u]=++step; visit[u]=1; instack[++index]=u; for(int i=head[u];i!=-1;i=edge[i].next) { if(!dfn[edge[i].to]) { tarjan(edge[i].to); low[u]=min(low[u],low[edge[i].to]); } else if(visit[edge[i].to]) { low[u]=min(low[u],dfn[edge[i].to]); } } if(low[u]==dfn[u]) { scc_cnt++; scc[scc_cnt].clear(); do { scc[scc_cnt].push_back(instack[index]); sccno[instack[index]]=scc_cnt; visit[instack[index]]=0; index--; } while(u!=instack[index+1]); } return; } bool dfs(int u) { for(int i=1;i<=scc_cnt;i++) { if(book[i]==0&&e[u][i]) { book[i]=1; if(match[i]==-1||dfs(match[i])) { match[i]=u; return true; } } } return false; } void init() { memset(instack,0,sizeof(instack)); memset(match,-1,sizeof(match)); memset(e,0,sizeof(e)); memset(visit,0,sizeof(visit)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(head,-1,sizeof(head)); memset(book,0,sizeof(book)); cnt=step=scc_cnt=index=ans=0; } int main() { int t; init(); scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&a[i].x,&a[i].y); add(a[i].x,a[i].y); } for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i); } for(int i=1;i<=m;i++) { if(sccno[a[i].x]!=sccno[a[i].y]) { e[sccno[a[i].x]][sccno[a[i].y]]=1; // e[sccno[a[i].y]][sccno[a[i].x]]=1; } } for(int i=1;i<=scc_cnt;i++) { memset(book,0,sizeof(book)); if(dfs(i)) ans++; } printf("%d ",scc_cnt-ans); init(); } return 0; }