[kuangbin带你飞]专题九 连通图 A - Network of Schools (强连通分量)(模板)

来源:互联网 发布:手机淘宝如何取消代付 编辑:程序博客网 时间:2024/05/21 08:40

强连通分量的模板题,设 a 为出度为1的点个数,设 b 为入度为1 的点个数,要求的是a和max(a,b)。

把处于一个强连通分量的点染色,再求出度和入度即可。

这里的模板是两个dfs,一个原图,一个逆图,两遍dfs即可求得结果,比较好理解。

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<stack>#include<vector>using namespace std;#define clr(a,b) memset(a,b,sizeof(a))#define pb(x) push_back(x)/*#define debug printf("test\n");typedef pair<int,int> pii;*/vector<int> g[105]; //原图vector<int> rg[105]; //反向图vector<int> ng[105]; //新图stack<int> s;int n,cnt,dfn[105],belong[105],id,vis[105],flag,ind[105],od[105]; //belong 缩点void dfs(int x) {if(vis[x] == flag) return ;vis[x] = flag;for(int i = 0;i < g[x].size();i++) dfs(g[x][i]);s.push(x);}void dfs2(int x) {if(vis[x] == flag) return ;vis[x] = flag; belong[x] = id;for(int i = 0;i < rg[x].size();i++) dfs2(rg[x][i]);}int main() {int n;while(scanf("%d",&n) != EOF) {for(int i = 0;i <= n;i++) {g[i].clear();rg[i].clear();}for(int i = 1;i <= n;i++) {int v;while(scanf("%d",&v) != EOF && v) {g[i].pb(v);rg[v].pb(i);}}flag = 1;clr(vis,0);for(int i = 1;i <= n;i++) {if(vis[i] != flag) {dfs(i);}}flag = 2;id = 0;for(int i = 1;i <= n;i++) {int tmp = s.top();if(vis[tmp] != flag) {++id;dfs2(tmp);}s.pop();}clr(ind,0);clr(od,0);for(int i = 1;i <= n;i++) {for(int j = 0;j < g[i].size();j++) {int v = g[i][j];if(belong[i] == belong[v]) continue;ind[belong[v]]++;od[belong[i]]++;}}if(id == 1) {printf("1\n0\n");continue;}int incnt = 0,outcnt = 0;for(int i = 1;i <= id;i++) {if(!ind[i]) incnt++;if(!od[i]) outcnt++;}printf("%d\n%d\n",incnt,max(outcnt,incnt));}}


0 0
原创粉丝点击