您的位置:首页 > 其它

POJ - 1236 Network of Schools 【有向图至少加多少条边变成强联通图】

2017-09-10 23:24 579 查看
传送门

//题意: 给定一幅有向图, 问:

1: 至少需要给几个人传递消息, 可以使图中任意点可以收到消息.

2: 至少加多少条边, 使得原图变成一幅强联通图.

//思路: 这个就很简单了, 就是一个水题. 随便分析一下就知道了. 对应答案就是缩完点后的图中入度为0的点数, max(入度为0的点数, 初度为0的点数). 注意一个坑点就是当缩完点后只有一个点时, 需要特判答案.

AC Code

/** @Cain*/
const int maxn = 1e2+5;
int dfn[maxn],low[maxn],bel[maxn];
int in[maxn],out[maxn];
int dfs_id,cnt;
vector<int>G[maxn];
stack<int >st;
void tarjan(int u){
dfn[u] = low[u] = ++dfs_id;
st.push(u);
for(int i=0; i<G[u].size(); i++){
int v = G[u][i];
//if(v == fa) continue;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(!bel[v])
low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u]){
cnt++;
while(1){
int v = st.top();
st.pop();
bel[v] = cnt;
if(v == u) break;
}
}
}

void solve()
{
int n;
while(~scanf("%d",&n)){
Fill(dfn,0); Fill(low,0);
Fill(bel,0); Fill(in,0); Fill(out,0);
dfs_id = cnt = 0;
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<=n;i++){
while(1){
int u ; scanf("%d",&u);
if(u == 0) break;
G[i].push_back(u);
}
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=n;i++){
for(int j=0;j<G[i].size();j++){
int v = G[i][j];
if(bel[i] != bel[v]){
in[bel[v]]++;
out[bel[i]]++;
}
}
}
if(cnt == 1){
printf("1\n0\n");
continue;
}
int cnt1 = 0 ,cnt2 = 0;
for(int i=1;i<=cnt;i++){
if(!in[i]) cnt1++;
if(!out[i]) cnt2++;
}
printf("%d\n%d\n",cnt1,max(cnt1,cnt2));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: