首页 > 代码库 > Poj 1144 Zoj 1311 求割点 模板
Poj 1144 Zoj 1311 求割点 模板
写这个就是为了手写一份好用的求割点模板:
吐槽下,题目中的 Each of the next at most N lines contains the number of a place followed by the numbers of some places to which there is a direct line from this place. 这个at most是不可信的,应该是用大于n行的测试数据,因为这个我WA了。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 100+10;
int mat[MAXN][MAXN],son,subset[MAXN],dfn[MAXN],low[MAXN],vis[MAXN],tmpdfn;
//son,subset记录连通分量个数,
//如果是根节点,son==把根节点去掉后的连通分支个数,
//如果不是根节点,subset[i]+1==把该节点去掉后的连通分支个数
//所以根节点和其他节点区分开了
int n;
void init()
{
son=tmpdfn=0;
memset(vis,0,sizeof(vis));
memset(mat,0,sizeof(mat));
memset(subset,0,sizeof(subset));
memset(dfn,0,sizeof(dfn));
int u,v;
char ch;
while (scanf("%d",&u),u)
{
while(getchar()!=‘\n‘)
{
scanf("%d",&v);
mat[u][v]=mat[v][u]=1;
}
}
}
void dfs(int u)
{
dfn[u]=low[u]=tmpdfn++;
for(int i=1;i<=n;i++)
{
if(mat[u][i])
if(!vis[i])
{
vis[i]=1;
dfs(i);
low[u]=min(low[u],low[i]);
if(low[i]>=dfn[u])//关节点的第二个条件
{
if(1 == u)son++;
else subset[u]++;
}
}
else
low[u]=min(low[u],dfn[i]);
//low[u]=Min{dfn[u],Min{low[w]|w是u的一个子女},Min{dfn[v]|v与u邻接,且(u,v)是一条回边}}
//此处就是回边的情况,所以是dfn[i]而不是low[i],!!!注意low的定义
}
}
int solve()
{
init();
for(int i=1;i<=n;i++)//可能本身不是连通图
if(!vis[i])
{
vis[i]=1;
dfs(i);
if(son)
{
subset[i]=son-1;
son=0;
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(subset[i])ans++;//subset[i]+1就是去掉割点后所形成的连通分支个数
}
return ans;
}
int main()
{
//freopen("poj1144.txt","r",stdin);
while(~scanf("%d",&n) && n)
{
printf("%d\n",solve());
}
return 0;
}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。