您的位置:首页 > 其它

UVALive - 5135 Mining Your Own Business

2013-09-23 22:58 423 查看
刘汝佳白书上面的一道题目:题意是给定一个联通分量,求出割顶以及双连通分量的个数,并且要求出安放安全井的种类数,也就是每个双连通分量中结点数(除开 割顶)个数相乘,对于有2个及以上割顶的双连通分量可以不用安放安全井。如果整个图就是一个双连通分量,那么需要安放两个安全井,种类数是n*(n-1)/2.

代码来自刘汝佳白书:

#include <iostream>
#include <sstream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pi acos(-1.0)
#define pb push_back
#define mp(a, b) make_pair((a), (b))
#define in  freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define stop  system("pause");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x0f0f0f0f
#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;
typedef long long  LL;
typedef vector<int> VI;
typedef pair<int, int> pii;
typedef vector<pii,int> VII;
typedef vector<int>:: iterator IT;
const int maxn = 50000 + 10;
int pre[maxn], low[maxn], iscut[maxn], dfs_clock;
VI g[maxn], cut;
int n;
LL ans1, ans2, cut_cnt;
int dfs(int u, int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = 0;
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(!pre[v])
{
child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if(lowv >= pre[u])
{
iscut[u] = 1;
}
}
else if(pre[v] < pre[u] && v != fa)
{
lowu = min(lowu, pre[v]);
}
}
if(child == 1 && fa < 0)
iscut[u] = 0;
return low[u] = lowu;
}
void find_bcc(int n)
{
memset(pre, 0, sizeof(pre));
memset(iscut, 0, sizeof(iscut));
dfs_clock = 0;
for(int  i = 0; i < n; i++)
if(!pre[i])
dfs(i, -1);
}
int cnt;
void dfs1(int u)
{
cnt++;
pre[u] = 1;
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(!pre[v])
{
if(iscut[v]) cut_cnt++, cnt++, pre[v] = 1, cut.pb(v);
else dfs1(v);
}
}
}
void solve(int n)
{
cut.clear();
cut_cnt= 0;
memset(pre, 0, sizeof(pre));
for(int i = 0; i < n; i++)
if(iscut[i]) cut_cnt++;

if(cut_cnt == 0) ans1 = 2, ans2 = (LL)n*(n-1)/2;
else for(int i = 0; i < n; i++)
if(!pre[i] && !iscut[i])
{
cut_cnt = cnt = 0;
dfs1(i);
for(int i = 0; i  < cut.size(); i++)
pre[cut[i]] = 0;
cut.clear();
if(cut_cnt == 1)
ans1++, ans2 *= (LL)(cnt-1);
}
}
int main(void)
{
int m, t = 1;
while(scanf("%d", &m), m)
{
n = 0;
ans1 = 0, ans2 = 1;
for(int i = 0; i < maxn; i++)
g[i].clear();
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
n = max(n, max(u, v));
u--, v--;
g[u].pb(v);
g[v].pb(u);
}
find_bcc(n);
solve(n);
printf("Case %d: %I64d %I64d\n", t, ans1, ans2);
t++;
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: