loj 1429(可相交的最小路径覆盖)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1429
思路:这道题还是比较麻烦的,对于求有向图的可相交的最小路径覆盖,首先要解决成环问题,可以先染色缩点重建图,然后就是如何来处理这个路径可以相交这个问题,这里可以用bfs求出任意两点之间是否可达,如果可达,就连边,然后就是HK算法求最大匹配了,最小路径覆盖 = 顶点数 - 最大匹配。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
using namespace std; const int MAXN = ( + );
const int MAXM = ( + );
int n, m;
int cnt, scc_count;
bool Instack[MAXN];
int low[MAXN], dfn[MAXN], color[MAXN];
vector<int > g[MAXN];
stack<int > S; void Tarjan(int u)
{
low[u] = dfn[u] = ++cnt;
Instack[u] = true;
S.push(u);
for (int i = ; i < (int)g[u].size(); i++) {
int v = g[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]) {
scc_count++;
int v;
do {
v = S.top();
S.pop();
Instack[v] = false;
color[v] = scc_count;
} while (u != v);
}
} bool Isok[MAXN][MAXN];
bool mark[MAXN];
vector<int > reg[MAXN]; void bfs(int st)
{
memset(mark, false, sizeof(mark));
queue<int >que;
que.push(st);
mark[st] = true;
while (!que.empty()) {
int u = que.front();
que.pop();
for (int i = ; i < (int)reg[u].size(); i++) {
int v = reg[u][i];
if (!mark[v]) {
mark[v] = true;
que.push(v);
}
}
}
} void Build()
{
for (int i = ; i <= scc_count; i++) {
reg[i].clear();
}
for (int i = ; i <= scc_count; i++) {
for (int j = ; j <= scc_count; j++) {
if (i != j && Isok[i][j]) {
reg[i].push_back(j);
}
}
}
} int lx[MAXN], ly[MAXN];
int distx[MAXN], disty[MAXN]; bool MaxMatch_bfs()
{
bool flag = false;
memset(distx, , sizeof(distx));
memset(disty, , sizeof(disty));
queue<int > que;
for (int i = ; i <= scc_count; i++) {
if (lx[i] == -) que.push(i);
}
while (!que.empty()) {
int u = que.front();
que.pop();
for (int i = ; i < (int)reg[u].size(); i++) {
int v = reg[u][i];
if (disty[v] == ) {
disty[v] = distx[u] + ;
if (ly[v] == -) flag = true;
else {
distx[ly[v]] = disty[v] + ;
que.push(ly[v]);
}
}
}
}
return flag;
} int dfs(int u)
{
for (int i = ; i < (int)reg[u].size(); i++) {
int v = reg[u][i];
if (disty[v] == distx[u] + ) {
disty[v] = ;
if (ly[v] == - || dfs(ly[v])) {
ly[v] = u;
lx[u] = v;
return ;
}
}
}
return ;
} int MaxMatch()
{
memset(lx, -, sizeof(lx));
memset(ly, -, sizeof(ly));
int res = ;
while (MaxMatch_bfs()) {
for (int i = ; i <= scc_count; i++) {
if (lx[i] == -) res += dfs(i);
}
}
return res;
} int main()
{
int _case, t = ;
scanf("%d", &_case);
while (_case--) {
scanf("%d %d", &n, &m);
for (int i = ; i <= n; i++) {
g[i].clear();
reg[i].clear();
}
while (m--) {
int u, v;
scanf("%d %d", &u, &v);
g[u].push_back(v);
}
//强联通缩点重建图
cnt = scc_count = ;
memset(dfn, , sizeof(dfn));
for (int i = ; i <= n; i++) {
if (dfn[i] == ) Tarjan(i);
}
for (int u = ; u <= n; u++) {
for (int i = ; i < (int)g[u].size(); i++) {
int v = g[u][i];
if (color[u] != color[v]) {
reg[color[u]].push_back(color[v]);
}
}
}
//bfs求出新图中的任意两点之间是否可达
memset(Isok, false, sizeof(Isok));
for (int i = ; i <= scc_count; i++) {
bfs(i);
for (int j = ; j <= scc_count; j++) {
if (mark[j]) {
Isok[i][j] = true;
}
}
}
//对于那些可达的点重新连边
Build();
//bfs求解最大匹配;
//最小路径覆盖 = 顶点数 - 最大匹配数
int ans = MaxMatch();
printf("Case %d: %d\n", t++, scc_count- ans);
}
return ;
}
loj 1429(可相交的最小路径覆盖)的更多相关文章
- POJ2594 Treasure Exploration【DAG有向图可相交的最小路径覆盖】
题目链接:http://poj.org/problem?id=2594 Treasure Exploration Time Limit: 6000MS Memory Limit: 65536K T ...
- poj 2594(可相交的最小路径覆盖)
题目链接:http://poj.org/problem?id=2594 思路:本来求最小路径覆盖是不能相交的,那么对于那些本来就可达的点怎么处理,我们可以求一次传递闭包,相当于是加边,这样我们就可以来 ...
- Treasure Exploration POJ - 2594 【有向图路径可相交的最小路径覆盖】模板题
Have you ever read any book about treasure exploration? Have you ever see any film about treasure ex ...
- poj 2594Treasure Exploration(有向图路径可相交的最小路径覆盖)
1 #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> ...
- HDU 4606 Occupy Cities ★(线段相交+二分+Floyd+最小路径覆盖)
题意 有n个城市,m个边界线,p名士兵.现在士兵要按一定顺序攻占城市,但从一个城市到另一个城市的过程中不能穿过边界线.士兵有一个容量为K的背包装粮食,士兵到达一个城市可以选择攻占城市或者只是路过,如果 ...
- Loj 6002 最小路径覆盖(最大流)
题意: 求不相交的最小路径覆盖 思路: 连边跑二分图,匹配一条边相当于缩了一条边,答案为n-maxflow 如果是求可以相交的最小路径覆盖的话,先用Floyd跑出可达矩阵,然后所有可达的点连边跑二分图 ...
- Light OJ 1429 Assassin`s Creed (II) BFS+缩点+最小路径覆盖
题目来源:Light OJ 1429 Assassin`s Creed (II) 题意:最少几个人走全然图 能够反复走 有向图 思路:假设是DAG图而且每一个点不能反复走 那么就是裸的最小路径覆盖 如 ...
- [LOJ#6002]「网络流 24 题」最小路径覆盖
[LOJ#6002]「网络流 24 题」最小路径覆盖 试题描述 给定有向图 G=(V,E).设 P 是 G 的一个简单路(顶点不相交)的集合.如果 V 中每个顶点恰好在 P 的一条路上,则称 P 是 ...
- POJ 2594 Treasure Exploration (可相交最小路径覆盖)
题意 给你张无环有向图,问至少多少条路径能够覆盖该图的所有顶点--并且,这些路径可以有交叉. 思路 不是裸的最小路径覆盖,正常的最小路径覆盖中两个人走的路径不能有重复的点,而本题可以重复. 当然我们仍 ...
随机推荐
- MyBatis <if>标签的一些问题
1.常见错误: There is no getter for property named 'parentId' in 'class java.lang.Long'(或者String) org.myb ...
- iOS 开启data protection 的方法
我这里说的data protection,指的是设备设置密码后,如果设备锁屏,并且当前解锁需要密码(有时可能因为自己的设定,导致会再几小时后才需要密码),这时应用程序处于加密状态,无法从外部读取.如果 ...
- jquery checkbox 限制多选的个数
2015年11月6日 16:32:49 选中第四个的时候提示超过了3个, 点解alert框取消后, 将最后一个选中的checkbox取消选中 <script> $(document).re ...
- Mac下DIY文件浏览器
2015-07-14 15:07:53 Mac下的finder不能浏览Linux文件目录, 一些优秀的资源管理器是收费的..... 于是想到了既然Mac的本质是类Unix, 而在windows下查看L ...
- “假学习“&”真学习“?(摘)
什么叫做“假学习”? 一.看书 买一堆书,有空看看.看书,这是典型的假学习.看书看不懂还在看,就是假学习,欺骗自己,安慰自己正在学习而已.专业书都写得很好,但大都是写给已经懂的人看的.看书的最大作用就 ...
- Effective C++ -----条款34:区分接口继承和实现继承
接口继承和实现继承不同.在public继承之下,derived classes总是继承base class的接口. pure virtual函数只具体指定接口继承. 简朴的(非纯)impure vir ...
- html中的alt和title用法区别
html中的alt和title用法区别 首先明确一下概念,alt是html标签的属性,而title既是html标签,又是html属性.title标签这个不用多说,网页的标题就是写在<title& ...
- sqlserver 解析Json字符串
转自:https://www.simple-talk.com/sql/t-sql-programming/consuming-json-strings-in-sql-server/ http://ww ...
- [Android Pro] CountDownTimer倒计时
定时执行在一段时候后停止的倒计时,在倒计时执行过程中会在固定间隔时间得到通知(译者:触发onTick方法),下面的例子显示在一个文本框中显示一个30s倒计时: new CountdownTimer(3 ...
- 【转】深入Windows内核——C++中的消息机制
上节讲了消息的相关概念,本文将进一步聊聊C++中的消息机制. 从简单例子探析核心原理 在讲之前,我们先看一个简单例子:创建一个窗口和两个按钮,用来控制窗口的背景颜色.其效果 图1.效果图 Win32 ...