/*
translation:
n个学校组成一个网络,给出链接情况(单向图)。求要使得报文能够发往全部学校,最少需要发送多少个报文。
要使得从任何一个学校能够到达任何一个学校,最少需要添加几条边?
solution:
强联通分量,缩点
缩点后整张图就成了DAG,那么显然地第一个问题就是DAG上入度为0的点。主要在于第二个问题。如何添边才能得到最优解呢?
方法如下:首先缩点后,可以得到一个DAG,然后求出DAG中所有的子树(入度0的点和该点出发可达的所有出度为0的点就构成了一个子树)。
从子树的叶节点开始往其他子树的根节点连上边,这样得到的就是最优解了。可以看出第二个问题答案就是max(out, in)。其中out,in
分别为出度入度0的节点个数。
note:
当强联通分量只有一个时需要特殊处理。
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 100 +5;
int V;
vector<int> G[maxn];
vector<int> rG[maxn];
vector<int> vs;
bool used[maxn];
int cmp[maxn], out[maxn], in[maxn];
struct Edge
{
int from, to;
Edge(int f, int t):from(f),to(t){}
Edge() {}
};
vector<Edge> edges;
void add_edge(int from, int to)
{
edges.push_back(Edge(from, to));
G[from].push_back(to);
rG[to].push_back(from);
}
void dfs(int v)
{
used[v] = true;
for(int i = 0; i < G[v].size(); i++) {
if(!used[G[v][i]]) dfs(G[v][i]);
}
vs.push_back(v);
}
void rdfs(int v, int k)
{
used[v] = true;
cmp[v] = k;
for(int i = 0; i < rG[v].size(); i++) {
if(!used[rG[v][i]]) rdfs(rG[v][i], k);
}
}
int scc()
{
memset(used, 0, sizeof(used));
vs.clear();
for(int v = 0; v < V; v++) {
if(!used[v]) dfs(v);
}
memset(used, 0, sizeof(used));
int k = 0;
for(int i = vs.size() - 1; i >= 0; i--) {
if(!used[vs[i]]) rdfs(vs[i], k++);
}
return k;
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%d", &V)) {
for(int i = 0; i < maxn; i++) {
G[i].clear();
rG[i].clear();
}
edges.clear();
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(cmp, 0, sizeof(cmp));
int id;
for(int i = 0; i < V; i++) {
for(;;) {
scanf("%d", &id);
if(id == 0) break;
add_edge(i, id - 1);
}
}
int k = scc(); //求出强联通分量的个数
if(k == 1) {
printf("1\n0\n");
continue;
}
for(int i = 0; i < edges.size(); i++) {
int s = edges[i].from, t = edges[i].to;
if(cmp[s] != cmp[t]) {
out[cmp[s]]++; in[cmp[t]]++;
}
}
int ans0 = 0;
for(int i = 0; i < k; i++)
if(!in[i]) ans0++;
printf("%d\n", ans0);
int ans1 = 0;
for(int i = 0; i < k; i++)
if(!out[i]) ans1++;
ans1 = max(ans1, ans0);
printf("%d\n", ans1);
}
return 0;
}
poj1236(*强连通分量,缩点)
最新推荐文章于 2021-04-20 22:07:11 发布