一开始写这题,心想的就是贪心去写,但是bzoj上一直wa,心想能拿到一点分吧,就去洛谷找这题,交一发,发现0分。。。wa的一声就哭了
然后看别人题解去了,原来是求割点的题,没写过(摔
然后百度了一波模板题写了一法写的好辛苦。。。
然后终于回到这题了。我的思路是:求出割点,你会发现割点根本不可以建救援点。所以把割点全部去掉,然后跑一边整个图看看有多少个联通块就好了。然后只有30分(
但是这里有个问题,就是如果一个联通块同时连着两个或以上的割点,那么他自己本身肯定是不用救援点的,我们统计的时候就不用加入这个联通块里面的情况。
比如一组数据
6
1 2
2 4
2 3
3 5
3 6
4 5
你可以堵住2这个割点,你会发现4 5组成的连通块是可以到达6这个连通块出去的,堵住3也一样。
然后稍加修改,就满分了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
set <int> s;
vector <int> G[505];
int n;
ll cnt;
bool is_cut[505], vst[505];
int dfn[505], low[505], par[505], ind;
void Tarjan(int u, int Father)
{
par[u] = Father;
dfn[u] = low[u] = ind++;
int son = 0;
for(int j = 0; j < G[u].size(); ++j)
{
int v = G[u][j];
if(v == Father) //只能向下遍历
continue;
if(dfn[v] == -1)
{
son++; //若u为割点,可以分出的联通块数目,该项只对树根有效
Tarjan(v, u);
low[u] = min(low[u], low[v]);
if(u != Father && low[v] >= dfn[u]) { //当u不是树根时,如果存在low >= dfn这种情况
is_cut[u] = 1; //说明u是一个割点,并且记录下其分割出来的联通块的数目
}
}
else if(v != Father)
low[u] = min(low[u], dfn[v]);
}
if(u == Father && son > 1) //如果u等于father,则说明它是树根。此时若其次数大于2则
is_cut[u] = 1; //该树根为割点
}
void dfs(int u) {
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(is_cut[v]) {
s.insert(v);
} else if (!vst[v]) {
cnt++;
vst[v] = 1;
dfs(v);
}
}
}
int main() {
int Case = 1;
while(cin >> n) {
if(n == 0)
break;
int Max_ind = 0;
for(int i = 0; i < 505; i++)
G[i].clear();
memset(is_cut, 0, sizeof(is_cut));
memset(vst, 0, sizeof(vst));
memset(dfn, -1, sizeof(dfn));
for(int i = 0; i < n; i++) {
int u, v;
cin >> u >> v;
Max_ind = max(Max_ind, u);
Max_ind = max(Max_ind, v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = 1; i <= Max_ind; i++) {
if(dfn[i] == -1)
Tarjan(i, i);
}
int num = 0;
ll ans = 1;
for(int i = 1; i <= Max_ind; i++) {
if(!is_cut[i] && !vst[i]) {
s.clear();
vst[i] = 1;
cnt = 1;
dfs(i);
if(s.size() > 1)
continue;
num++;
ans *= cnt;
}
}
if(Max_ind == 1)
printf("Case %d: 1 1\n", Case++);
else if(num == 1) {
ans = (Max_ind * (Max_ind - 1)) / 2;
printf("Case %d: 2 %lld\n", Case++, ans);
}
else
printf("Case %d: %d %lld\n", Case++, num, ans);
}
return 0;
}