您的位置:首页 > 其它

UVALive 6044(双连通分量的应用)

2013-09-14 09:57 309 查看
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34902

思路:首先是双连通缩点,然后就是搜索一下,搜索时要跳过连通分量的点的个数>=2的点,最后的答案是n*(n-1)/2.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
#define MAXN 11111
#define MAXM 444444

struct Edge{
int v,next;
}edge[MAXM];

int n,m,NE,cnt,_count;
int head[MAXN];

void Insert(int u,int v)
{
edge[NE].v=v;
edge[NE].next=head[u];
head[u]=NE++;
}

int low[MAXN],dfn[MAXN];
int color[MAXN];
bool mark[MAXN];
stack<int>S;
void Tarjan(int u,int father)
{
int flag=0;
low[u]=dfn[u]=++cnt;
mark[u]=true;
S.push(u);
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==father&&!flag){ flag=1;continue; }
if(dfn[v]==0){
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}else if(mark[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
_count++;
int x=S.top();
if(x==u)S.pop();
else {
do{
x=S.top();
S.pop();
mark[x]=false;
color[x]=_count;
}while(x!=u);
}
}
}

int ans;
void dfs(int u,int father)
{
color[u]=1;
_count++;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==father)continue;
if(color[v])continue;
dfs(v,u);
}
}

int main()
{
int _case,u,v,t=1;
scanf("%d",&_case);
while(_case--){
scanf("%d%d",&n,&m);
NE=0;
memset(head,-1,sizeof(head));
while(m--){
scanf("%d%d",&u,&v);
Insert(u,v);
Insert(v,u);
}
cnt=_count=0;
memset(dfn,0,sizeof(dfn));
memset(color,0,sizeof(color));
for(int i=1;i<=n;i++){
if(dfn[i]==0)Tarjan(i,-1);
}
ans=0;
for(int i=1;i<=n;i++){
if(color[i]==0){
_count=0;
dfs(i,-1);
ans+=_count*(_count-1)/2;
}
}
printf("Case #%d: %d\n",t++,ans);
}
return 0;
}


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