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;
}
#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;
}
相关文章推荐
- 166. Fraction to Recurring Decimal
- OpenCL异构计算资料收集
- QT项目笔记
- xfire客户端调用webservice测试
- [BZOJ3997]TJOI2015组合数学|DP
- 调用系统相机以及 打开相册的代码
- OpenCL异构计算资料收集
- ImageViewCoverflow
- corosync/pacemaker, 实现高可用的MariaDB
- 各类移动安全竞赛题/部分writeup收集与整理
- MyBatis学习总结(五)——实现关联表查询
- Ant自动编译打包android项目
- delphi XE8 正式破解版下载、注册码
- 凯云水利水电工程造价管理系统 技术解析(九)机械单价(四)
- SSH2.0编程 ssh协议过程实现
- mysql 时间日期查询
- !HDU 2602 Bone Collector--DP--(裸01背包)
- 黑马程序员-java之网络编程
- ceph pg(placement group)状态总结
- 四句话