您的位置:首页 > 产品设计 > UI/UE

hdu 3836 Equivalent Sets

2014-10-09 16:48 267 查看
强联通的题。

给出一个图,求最少几步把图组成强联通图。。。

首先先根据图把图建好,然后把每个强联通子图构成一个点。

附上代码:

#include<stdio.h>
#include<string.h>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int mx=50010;
int vis[mx];
int low[mx],dfn[mx];
int color[mx];
int n,m,index,cnt,top;
int stack[mx];
int lt[mx],rt[mx];
vector <int> mp[mx];
void init() //初始化
{
index=cnt=top=0;
for(int i=0; i<mx; i++)
{
low[i]=0;
dfn[i]=0;
color[i]=0;
vis[i]=0;
lt[i]=0;
rt[i]=0;
mp[i].clear();
}
}
void tarjan(int u) //普通的tarjan 加缩点
{
dfn[u]=low[u]=++index;
vis[u]=1;
stack[top++]=u;
for(int i=0; i<mp[u].size(); i++)
{
int v=mp[u][i];
if(dfn[v]==0)
{
tarjan(v);
low[u]=low[u]<low[v]?low[u]:low[v];
}
else if(vis[v]&&dfn[v]<low[u])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
cnt++;
int v;
do
{
v=stack[--top];
vis[v]=0;
color[v]=cnt; //缩点的核心就是将联通分量标记成相同。
}
while(u!=v);
}
}
void sove()
{
//进行一次tarjan 算法,并进行缩点操作。
for(int i=1; i<=n; i++)
{
if(dfn[i]==0)
tarjan(i);
}
if(cnt==1)
{
printf("0\n");
return ;
}
//统计入度、出度。
for(int i=1; i<=n; i++)
{
for(int j=0; j<mp[i].size(); j++)
{
int k=mp[i][j];
if(color[i]!=color[k])
{
lt[color[i]]++;
rt[color[k]]++;
}
}
}
int l=0,r=0;
for(int i=1; i<=cnt; i++)
{
if(lt[i]==0)
l++;
if(rt[i]==0)
r++;
}
printf("%d\n",l>r?l:r);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
mp[u].push_back(v);
}
sove();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: