您的位置:首页 > 其它

poj 1236 Network of Schools(强连通分量构造强连通图)

2016-10-02 21:02 288 查看
题目:http://poj.org/problem?id=1236

题意:

N(2< N< 100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。

分析:

先找出强连通分量,缩点,得到一个DAG。对于问题1,显然只要一个点有入度,那么就可以传进来,所以找入度为0的点的个数即可。对于问题2,相当于在加多少条边,可以得到强连通图?答案就是max{ 入度为0的点数,出度为0的点数 },为什么?因为一个点必须有入度和出度。

代码:

using namespace std;

const int N = 100 + 10;
vector<int> G
;
int pre
, lowlink
, sccno
, dfs_clock, scc_cnt;
stack<int> S;

void dfs(int u) {
pre[u] = lowlink[u] = ++dfs_clock;
S.push(u);
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(!pre[v]) {
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
} else if(!sccno[v]) {
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if(lowlink[u] == pre[u]) {
++scc_cnt;
int x;
do {
x = S.top();
S.pop();
sccno[x] = scc_cnt;
} while(x!=u);
}
}

void find_scc(int n) {
dfs_clock = scc_cnt = 0;
memset(sccno, 0, sizeof(sccno));
memset(pre, 0, sizeof(pre));
for(int i = 0; i < n; i++)
if(!pre[i]) dfs(i);
}

int in0
, out0
;

int main() {
int  n, m,x;
//freopen("f.txt","r",stdin);
scanf("%d", &n);
for(int i = 0; i < n; i++) G[i].clear();
for(int i = 0; i < n; i++) {
while(scanf("%d",&x)&&x) {
G[i].push_back(x-1);
}
}
find_scc(n);

for(int i = 1; i <= scc_cnt; i++) in0[i] = out0[i] = 1;
for(int u = 0; u < n; u++)
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(sccno[u] != sccno[v]) in0[sccno[v]] = out0[sccno[u]] = 0;
}
int a = 0, b = 0;
for(int i = 1; i <= scc_cnt; i++) {
if(in0[i]) a++;
if(out0[i]) b++;
}
int ans = max(a, b);
if(scc_cnt == 1) ans = 0;
printf("%d\n%d\n", a,ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: