B - Network of Schools POJ - 1236(Tarjan求強連通分量+縮點)
阿新 • • 發佈:2019-01-14
題意:
給出你一個圖,代表許多學校的網路連線情況,第一個問題:要想把一個資訊傳輸到所有節點至少要在幾個節點上放置資訊。第二個問題:想要把整個圖變成強連通圖需要增加多少條邊。
思路:
對於第一個問題,找到所有的強連通分量,然後把其縮成一個點,然後再看整個圖,統計一下入度為0的點,就是答案(PS:注意整個圖是強連通圖,也就是入度為0的點不存在,這時應該輸出1)。
對於第二個問題,還是和每個節點的度有關係(縮點之後的),統計出度為0的點的數量和入度為0的點的數量,我們要保證取縮點之後不存在出度為0或入度為0的點,所以取二者最大值即為答案(我們可以在入度為0和出度為0的點之間建邊,多餘的點隨便拉一條邊接到其他節點上就行)。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1020;
int n, tot, num, top, sum;
int head[maxn], Stack[maxn], dfn[maxn], color[maxn];
int low[maxn], degree_in[maxn], degree_out[maxn];
struct node
{
int v, next;
}edge[maxn * 10];
inline void add(int u, int v) {
edge[tot].v = v;
edge[tot].next = head[u];
head[u] = tot++;
}
inline void Init() {
top = 0;
sum = 0;
num = 0;
tot = 0;
memset(head, -1, sizeof(head));
memset(dfn, -1, sizeof(dfn));
memset(degree_in, 0, sizeof(degree_in));
memset (degree_out, 0, sizeof(degree_out));
}
void Tarjan(int u)
{
dfn[u] = low[u] = ++num;
Stack[++top] = u;
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if(dfn[v] == -1) { //如果沒有被訪問過
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(color[v] == 0) { //如果被訪問過,但是不是其他強連通分量的一部分
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u]) { //找到一個強連通分量
color[u] = ++sum; //重新編號,相當於縮點
while(Stack[top] != u) {
color[Stack[top--]] = sum;
}
top --;
}
}
int main()
{
//freopen("in.txt", "r", stdin);
cin >> n;
Init();
for(int i = 1; i <= n; ++ i) {
int v;
while(1) {
scanf("%d", &v);
if(v == 0) break;
add(i, v);
}
}
for(int i = 1; i <= n; ++ i) { //不一定是連通圖
if(dfn[i] == -1) Tarjan(i);
}
for(int i = 1; i <= n; ++ i) {
for(int j = head[i]; j != -1; j = edge[j].next) {
int v = edge[j].v;
if(color[v] != color[i]) { //不是一個強連通分量的話就連線,但是沒有實際操作,只是記錄一下出度和入度,有需要的話可以直接連線
degree_in[color[v]] ++;
degree_out[color[i]] ++;
}
}
}
int in = 0, out = 0;
for(int i = 1; i <= sum; ++ i) {
if(degree_in[i] == 0) in++;
if(degree_out[i] == 0) out++;
}
if(sum == 1) //注意整個圖都是強連通圖的話要特判一下
printf("1\n0\n");
else
printf("%d\n%d\n", in, max(in, out));
return 0;
}