hdu 3861 强连通分量缩点+二分匹配求最小路径覆盖
来源:互联网 发布:java数组末尾添加元素 编辑:程序博客网 时间:2024/05/16 06:31
//用tarjan求出强连通分量,再将强连通分量的所有点缩为一个点
//具体的tarjan算法http://www.cnblogs.com/saltless/archive/2010/11/08/1871430.html
//然后重新建图,很容易想到剩下的是一个最小路径覆盖的题目
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 50100;
int low[maxn];
int dfn[maxn];
int vis[maxn];
int stack[maxn];
int instack[maxn];
int match[maxn];
int belong[maxn];
int top,step,num;
vector<int> vec_1[maxn];
vector<int> vec_2[maxn];
int dx[maxn*2],dy[2*maxn];
int n ,m;
void init()
{
step = top = num = 0;
memset(instack,0,sizeof(instack));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
for(int i = 0;i <= n;i++)
{
vec_1[i].clear();
vec_2[i].clear();
}
}
void tarjan(int u)
{
stack[++top] = u;
instack[u] = 1;
low[u] = dfn[u] = ++step;
for(int i = 0; i < vec_1[u].size() ;i++)
{
int v= vec_1[u][i];
if(!dfn[v])
{
tarjan(v) ;
low[u] = min(low[u],low[v]);
}
else if(instack[v])
low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u])
{
num ++;
int v = 0 ;
while(u!=v)
{
v = stack[top--];
belong[v] = num;
instack[v] = 0;
}
}
}
int find(int start)
{
for(int i = 0;i < vec_2[start].size();i++)
{
int v = vec_2[start][i];
if(!vis[v])
{
vis[v] = 1;
if(match[v] == -1 || find(match[v]))
{
match[v] = start;
return 1;
}
}
}
return 0;
}
void Match()
{
memset(match, -1,sizeof(match));
int ans = 0;
for(int i = 1;i <= num ;i++)
{
memset(vis,0,sizeof(vis));
if(find(i))
ans++;
}
printf("%d\n",num - ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i = 1;i <= m ;i++)
{
scanf("%d%d",&dx[i] ,&dy[i]);
vec_1[dx[i]].push_back(dy[i]);
}
for(int i = 1;i <= n;i++)
if(!dfn[i])
tarjan(i);
for(int i = 1;i <= m;i++)
{
int u = belong[dx[i]];
int v = belong[dy[i]];
if(u == v)continue;
vec_2[u].push_back(v);
}
Match();
}
return 0;
}
//具体的tarjan算法http://www.cnblogs.com/saltless/archive/2010/11/08/1871430.html
//然后重新建图,很容易想到剩下的是一个最小路径覆盖的题目
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 50100;
int low[maxn];
int dfn[maxn];
int vis[maxn];
int stack[maxn];
int instack[maxn];
int match[maxn];
int belong[maxn];
int top,step,num;
vector<int> vec_1[maxn];
vector<int> vec_2[maxn];
int dx[maxn*2],dy[2*maxn];
int n ,m;
void init()
{
step = top = num = 0;
memset(instack,0,sizeof(instack));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
for(int i = 0;i <= n;i++)
{
vec_1[i].clear();
vec_2[i].clear();
}
}
void tarjan(int u)
{
stack[++top] = u;
instack[u] = 1;
low[u] = dfn[u] = ++step;
for(int i = 0; i < vec_1[u].size() ;i++)
{
int v= vec_1[u][i];
if(!dfn[v])
{
tarjan(v) ;
low[u] = min(low[u],low[v]);
}
else if(instack[v])
low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u])
{
num ++;
int v = 0 ;
while(u!=v)
{
v = stack[top--];
belong[v] = num;
instack[v] = 0;
}
}
}
int find(int start)
{
for(int i = 0;i < vec_2[start].size();i++)
{
int v = vec_2[start][i];
if(!vis[v])
{
vis[v] = 1;
if(match[v] == -1 || find(match[v]))
{
match[v] = start;
return 1;
}
}
}
return 0;
}
void Match()
{
memset(match, -1,sizeof(match));
int ans = 0;
for(int i = 1;i <= num ;i++)
{
memset(vis,0,sizeof(vis));
if(find(i))
ans++;
}
printf("%d\n",num - ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i = 1;i <= m ;i++)
{
scanf("%d%d",&dx[i] ,&dy[i]);
vec_1[dx[i]].push_back(dy[i]);
}
for(int i = 1;i <= n;i++)
if(!dfn[i])
tarjan(i);
for(int i = 1;i <= m;i++)
{
int u = belong[dx[i]];
int v = belong[dy[i]];
if(u == v)continue;
vec_2[u].push_back(v);
}
Match();
}
return 0;
}
0 0
- hdu 3861 强连通分量缩点+二分匹配求最小路径覆盖
- HDU 3861 The King’s Problem (强连通分量缩点+二分图匹配最小路径覆盖)
- HDU 3861The King’s Problem 强连通分量分解 + 二分图最小路径覆盖
- hdu 1269 The King’s Problem(强连通分量+缩点+最小路径覆盖)
- HDU 3861--The King’s Problem【scc缩点构图 && 二分匹配求最小路径覆盖】
- hdu 3861(tarjan 缩点 + 二分图匹配 求最小路径覆盖
- HDU tarjan算法模版 强连通分量+最小路径覆盖
- 强连通+最小路径覆盖 hdu 3861
- SCU 4524 Division(强连通分量+缩点+最小路径覆盖)
- SCU 4529 An Easy Problem(强连通分量+缩点+最小路径覆盖+剪枝)
- hdu 3861 (强连通分量+最小路径覆盖)题意有些怪
- HDU - 3861 The King’s Problem(强连通分量+最小路径覆盖)
- The King’s Problem(tarjan求强连通分量缩点+匈牙利求有向无环图的最小路径覆盖)
- 强连通分量(强连通缩点(tarjan))+最小路径覆盖(匈牙利算法)
- hdu 3861强连通分量+最小图匹配
- HDOJ 3861 - The King’s Problem tarjan求强联通分量&缩点&有向图最小路径覆盖(匈牙利)
- HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)
- hdu-3861(强连通图缩点+二分图最小路径覆盖)
- URAL 1335 — White Thesis
- 树莓派2 HDMI-VGA 转换器黑屏的排障方案
- 核心分析28篇
- 设计模式之策略模式
- Android TextView显示文字对齐
- hdu 3861 强连通分量缩点+二分匹配求最小路径覆盖
- ROC曲线和Gini系数之间的关系
- C++ Primer Plus第六版编程练习7.10解答
- JAVA 开发平台的技术和框架(四)三、ORM :JPA
- C语言及程序设计.第七课.项目3.发工资
- tpm协议栈测试程序
- BZOJ 1027 JSOI 2007 合金 计算几何+最小环
- Paint&Canvas实现一个点(图片)在圆形(轨迹)上运动
- 【C语言】有一个分数序列2/1+3/2+5/3+8/5+13/8+…求出这个数列前20项的和。