您的位置:首页 > 其它

7_13_B题 Boonie and Clyde(tarjan求割点)

2016-09-04 15:38 337 查看

7_13_B题 Boonie and Clyde

题意

给出一张图,要求删去两个点,使图不连通,问有多少种删法。

思路

先tarjan求出所有割点,然后枚举要删去的第一个点,如果该点不是割点,则下一个点必须是割点,如果该点是割点,则要分类讨论,如果形成了三个或三个以上的连通块,则可任选下一点,如果形成了两个连通块,要分别考虑两边都只有一个点,有一边只有一个点的情况,再分别更新答案就行了

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e3 + 10;

int n, m, del, child, num;
int dfn[maxn], low[maxn], bricnt, times;
vector<int> G[maxn];
void init (){
memset(dfn, -1, sizeof(dfn));
memset(low, -1, sizeof(low));
}
inline void addedge(int from, int to){
G[from].push_back(to);
G[to].push_back(from);
}
void Tarjan(int cur , int from) {
dfn[cur] = low[cur] = ++times;
for(int i = 0; i < G[cur].size(); i++){
int to = G[cur][i];
if(to == del || to == from)continue;
if(dfn[to] == -1) {
Tarjan(to, cur);
low[cur] = min(low[cur] , low[to]);
if(from == 0) {
child++;
continue;
}
if(low[to] >= dfn[cur])
bricnt++;
}
else
low[cur] = min(low[cur] , dfn[to]);
}
}

int main() {
int kas = 1;
while(~scanf("%d %d", &n, &m) && (n + m)) {
while(m--) {
int u , v;
scanf("%d %d", &u, &v);
addedge(u, v);
}
printf("Case %d: ", kas++);
int ans = 0, sonnum;
for(del = 1; del <= n; del++) {
init();
int cnt = bricnt = sonnum = 0;
for(int i = 1; i <= n; i++)
if(i != del && dfn[i] == -1) {
cnt++;
times = child = 0;
Tarjan(i, 0);
if(times == 1) {
sonnum++;
continue;
}
if(child > 1) bricnt++ ;
}
if(cnt > 2)ans += (n - 1);

96ad
else if(cnt == 2 && sonnum == 0)ans += (n - 1);
else if(cnt == 2 && sonnum == 1)ans += (n - 2);
else if(cnt == 1)ans += bricnt;
}
printf("%d\n", ans / 2);
for(int i = 1; i <= n; i++) G[i].clear();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: