题目:http://poj.org/problem?id=1523
一开始没注意到空格,WA了一次,没注意到点的标记实际上是随意的,又WA了一次,实际上是枚举的思路:先找出所有割点,在对每个割点求出其将原图分成了几部分
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX_VERTEX 1001
bool used[MAX_VERTEX];
int N = 0, dfsClock, pre[MAX_VERTEX];
vector<int> connect[MAX_VERTEX];
int cutCount;
bool isCut[MAX_VERTEX];
int down, vis[MAX_VERTEX];
void dfs(int x)
{
vis[x] = down;
const vector<int>& v = connect[x];
for(int i = 0, n = v.size(); i < n; ++i){
if(v[i] != down && vis[v[i]] != down) dfs(v[i]);
}
}
int tarjan(int x, int fa)
{
int y, lowy, lowx = pre[x] = ++dfsClock, child = 0;
const vector<int>& v = connect[x];
for(int i = 0, n = v.size(); i < n; ++i){
y = v[i];
if(y == fa) continue;
if(!pre[y]){
++child;
lowy = tarjan(y, x);
lowx = min(lowx, lowy);
if(lowy >= pre[x]) isCut[x] = true;
}
else lowx = min(lowx, pre[y]);
}
if(fa == -1 && child < 2) isCut[x] = false;
if(isCut[x]) ++cutCount;
return lowx;
}
void solve()
{
//find cut nodes
memset(pre + 1, 0, N << 2);
memset(isCut + 1, false, N);
dfsClock = cutCount = 0;
tarjan(1, -1);
//check if cut exists
if(!cutCount){
puts(" No SPF nodes");
return;
}
//count each cut nodes' cut
memset(vis + 1, 0, N << 2);
for(int i = 1; i <= N; ++i){
if(!used[i] || !isCut[i]) continue;
down = i;
int cuts = 0;
for(int j = 1; j <= N; ++j){
if(!used[i] || j == down || vis[j] == down) continue;
++cuts;
dfs(j);
}
printf(" SPF node %d leaves %d subnets\n", down, cuts);
}
}
bool inputGraph()
{
int x, y;
scanf("%d", &x);
if(!x) return false;
else{
for(int i = 1; i <= N; ++i) connect[i].clear();
memset(used, false, sizeof(used));
N = 0;
}
do{
scanf("%d", &y);
connect[x].push_back(y);
connect[y].push_back(x);
used[x] = used[y] = true;
N = max(N, max(x, y));
}while(scanf("%d", &x), x);
return true;
}
int main()
{
int test = 0;
while(inputGraph()){
printf("Network #%d\n", ++test);
solve();
puts("");
}
return 0;
}
看了别人的分析之后,才明白原来一次tarjan算法就能在确定所有割点的同时,确定每个割点能将图分成几个分量,学习了……
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX_VERTEX 1001
bool used[MAX_VERTEX];
int N = 0, dfsClock, pre[MAX_VERTEX];
vector<int> connect[MAX_VERTEX];
bool isCut[MAX_VERTEX];
int cutCount, cutParts[MAX_VERTEX];
int tarjan(int x, int fa)
{
int y, lowy, lowx = pre[x] = ++dfsClock, child = 0;
const vector<int>& v = connect[x];
for(int i = 0, n = v.size(); i < n; ++i){
y = v[i];
if(y == fa) continue;
if(!pre[y]){
++child;
lowy = tarjan(y, x);
lowx = min(lowx, lowy);
if(lowy >= pre[x]){
isCut[x] = true;
++cutParts[x];
}
}
else lowx = min(lowx, pre[y]);
}
if(fa == -1 && child < 2) isCut[x] = false;
if(isCut[x]){
++cutCount;
if(fa != -1) ++cutParts[x];
}
return lowx;
}
void solve()
{
//find cut nodes
memset(pre + 1, 0, N << 2);
memset(isCut + 1, false, N);
memset(cutParts + 1, 0, N << 2);
dfsClock = cutCount = 0;
tarjan(1, -1);
//check if cut exists
if(!cutCount){
puts(" No SPF nodes");
return;
}
//count each cut nodes' cut
for(int i = 1; i <= N; ++i){
if(!used[i] || !isCut[i]) continue;
printf(" SPF node %d leaves %d subnets\n", i, cutParts[i]);
}
}
bool inputGraph()
{
int x, y;
scanf("%d", &x);
if(!x) return false;
else{
for(int i = 1; i <= N; ++i) connect[i].clear();
memset(used, false, sizeof(used));
N = 0;
}
do{
scanf("%d", &y);
connect[x].push_back(y);
connect[y].push_back(x);
used[x] = used[y] = true;
N = max(N, max(x, y));
}while(scanf("%d", &x), x);
return true;
}
int main()
{
int test = 0;
while(inputGraph()){
printf("Network #%d\n", ++test);
solve();
puts("");
}
return 0;
}