您的位置:首页 > 其它

HDU tarjan算法模版 强连通分量+最小路径覆盖

2015-06-03 20:45 337 查看
注意缩点之后,一个强连通分量内的点,不要在二分图拆点时连边。。

#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
struct arc
{
int to,val;
int next;
arc(int a=-1,int b=0):to(a),val(b) {}
};
int head[5050];
arc edge[100050];
int e_cnt=0;

int low[5050];//每一点通过儿子,回边可到达的最低深度优先数
int dfn[5050];//每一点的深度优先数
int stack[5050],top=0; //记录深搜的栈
int id[5050]; //每一点所属的强连通分量
int cnt; //记录深度优先数dfn所需递加的变量
int scnt; //强连通分量个数
int n,m; //n为顶点数 m为路径数

bool G[5050][5050]; //二分图
bool vis[5050];
int link[5050];

inline void addedge(int a,int b)
{
edge[e_cnt].to=b;
edge[e_cnt].next=head[a];
head[a]=e_cnt;
e_cnt++;
}

void dfs(int x)
{
low[x]=dfn[x]=++cnt;
stack[++top]=x;
int v;
for(int i=head[x];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
dfs(v);
low[x]=min(low[v],low[x]);
}
else if(!id[v]) low[x]=min(dfn[v],low[x]);
}
if(low[x]==dfn[x])
{
//printf("%d\n",x);
scnt++;
int tmp=0;
do
{
v=stack[top--];
id[v]=scnt;
}while(v!=x);
}
return;
}

void tarjan()
{
cnt=scnt=top=0;
memset(dfn,0,sizeof(dfn));
for(int i=1;i<=n;i++)
{
if(!dfn[i]) dfs(i);
}
return;
}

bool find(int u)
{
for(int i=1;i<=scnt;i++)
{
if(!vis[i]&&G[u][i])
{
vis[i]=true;
if(link[i]==-1||find(link[i]))
{
link[i]=u;
return true;
}
}
}
return false;
}

int slove()
{
int ans=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=scnt;i++)
{
memset(vis,0,sizeof(vis));
if(find(i)) ans++;
}
return ans;
}

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(id,0,sizeof(id));
memset(head,-1,sizeof(head));
e_cnt=0;
scanf("%d%d",&n,&m);
int a,b;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
}
tarjan();

// printf("%d\n",scnt);
// for(int i=1;i<=n;i++)
// {
// printf("i=%d id=%d\n",i,id[i]);
// }

memset(G,0,sizeof(G));
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=-1;j=edge[j].next)
{
if(id[i]==id[edge[j].to]) continue;
G[id[i]][id[edge[j].to]]=1;
}
}

// for(int i=1;i<=scnt;i++)
// {
// for(int j=1;j<=scnt;j++)
// {
// printf("%d
4000
",G[i][j]);
// }
// putchar('\n');
// }
// putchar('\n');
printf("%d\n",scnt-slove());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: