您的位置:首页 > 其它

POJ 1144 Network

2015-08-01 17:58 218 查看
求有几个割点。数据比较水,用了朴素方法。。。30ms。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

char s[1000000];
int n,u,v,tot,len,sum;
const int INF=0x7FFFFFFF;
const int MAXN=105;
vector<int>G[MAXN];
int fail[MAXN],flag[MAXN];

void DFS(int now)
{
int i;
for(i=0; i<G[now].size(); i++)
{
if(!flag[G[now][i]]&&!fail[G[now][i]])
{
flag[G[now][i]]=1;
DFS(G[now][i]);
}
}
}

int main()
{
int i,ii;
while(~scanf("%d",&n)&&n)
{
for(i=0; i<=n; i++) G[i].clear();
memset(flag,0,sizeof(flag));
memset(fail,0,sizeof(fail));
while(gets(s))
{
if(strcmp(s,"0")==0) break;
len=strlen(s);
u=INF;
sum=0;
for(i=0; i<=len; i++)
{
if(s[i]==' '||s[i]=='\0')
{
if(u==INF) u=sum,sum=0;
else
{
v=sum,sum=0;
G[u].push_back(v);
G[v].push_back(u);
}
}
else sum=sum*10+s[i]-'0';
}
}

memset(fail,0,sizeof(fail));

int AAA,ans=0;
for(ii=1; ii<=n; ii++)
{
fail[ii]=1;
AAA=0;
memset(flag,0,sizeof(flag));
for(i=1; i<=n; i++)
{
if(fail[i]) continue;
if(!flag[i])
{
flag[i]=1;
DFS(i);
AAA++;
}
}
if(AAA!=1) ans++;
fail[ii]=0;
}
printf("%d\n",ans);
}
return 0;
}


下面是用Tarjan算法的。跑了500ms的样子。。。。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

const int INF=0x7FFFFFFF;
const int maxn=1111;//有多少个结点
vector<int>G[maxn];
int visited[maxn];//标记该节点有没有访问过
int node,edge;//顶点数目
int tmpdfn;//dfs过程中记录当前的深度优先搜索序数
int dfn[maxn];//记录每个顶点的深度优先搜索序数
int low[maxn];//每个顶点的low值,根据该值来判断是否是关节点
int son;//根结点的有多少个孩子,如果大于等于2,则根结点为关节点
int subnets[maxn];//记录每个结点(去掉该结点后)的连通分量的个数
char s[maxn];

/*以下是输出重连通分量用的*/
int top;
struct Edge
{
int u,v;
void output()
{
printf("%d-%d ",u,v);
}
bool cmp(Edge &t)
{
return ((u==t.u&&v==t.v)||(v==t.u&&u==t.v));
}
};
Edge Stack[maxn];
int Flag[maxn][maxn];

void init()
{
for(int i=0; i<maxn; i++) G[i].clear();
low[1]=dfn[1]=1;
tmpdfn=1;
son=0;
memset(visited,0,sizeof(visited));
visited[1]=1;
memset(subnets,0,sizeof(subnets));
}

void dfs(int u)
{
for(int i=0; i<G[u].size(); i++)
{
int v=G[u][i];
Edge t;

/*将这条边压入栈顶*/
if(!Flag[u][v])//没有入过栈
{
t.u=u;
t.v=v;
Stack[++top]=t;
Flag[u][v]=Flag[v][u]=1;
}

if(!visited[v])
{
visited[v]=1;
tmpdfn++;
dfn[v]=low[v]=tmpdfn;
dfs(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
if(u!=1) subnets[u]++;
if(u==1) son++;
/*
printf("重连通分量:");
while(1)
{
if(top==-1) break;
Edge t1;
t1=Stack[top];
t1.output();
top--;
if(t1.cmp(t)) break;
}
printf("\n");
*/
}
}
else low[u]=min(low[u],dfn[v]);
}
}

int main()
{
while(~scanf("%d",&node)&&node)//输入节点数量和边的数量
{

init();//初始化

int len,u,v,sum;
while(gets(s))
{
if(strcmp(s,"0")==0) break;
len=strlen(s);
u=INF;
sum=0;
for(int i=0; i<=len; i++)
{
if(s[i]==' '||s[i]=='\0')
{
if(u==INF) u=sum,sum=0;
else
{
v=sum,sum=0;
G[u].push_back(v);
G[v].push_back(u);
}
}
else sum=sum*10+s[i]-'0';
}
}
top=-1;//初始化 栈为空
memset(Flag,0,sizeof(Flag));

//DFS求解割点,点双连通分量,去掉一个个点之后有几个连通分量
/*DFS过程中输出点双连通分量*/
dfs(1);

//计算根节点
if(son>1) subnets[1]=son-1;

int ans=0;

/*输出割点*/
for(int i=1; i<=node; i++)
if(subnets[i])
//printf("%d号节点是割点,删除之后有%d个连通分量\n",i,subnets[i]+1);
ans++;
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: