题目链接: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(可相交的最小路径覆盖)的更多相关文章

  1. POJ2594 Treasure Exploration【DAG有向图可相交的最小路径覆盖】

    题目链接:http://poj.org/problem?id=2594 Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K T ...

  2. poj 2594(可相交的最小路径覆盖)

    题目链接:http://poj.org/problem?id=2594 思路:本来求最小路径覆盖是不能相交的,那么对于那些本来就可达的点怎么处理,我们可以求一次传递闭包,相当于是加边,这样我们就可以来 ...

  3. Treasure Exploration POJ - 2594 【有向图路径可相交的最小路径覆盖】模板题

    Have you ever read any book about treasure exploration? Have you ever see any film about treasure ex ...

  4. poj 2594Treasure Exploration(有向图路径可相交的最小路径覆盖)

    1 #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> ...

  5. HDU 4606 Occupy Cities ★(线段相交+二分+Floyd+最小路径覆盖)

    题意 有n个城市,m个边界线,p名士兵.现在士兵要按一定顺序攻占城市,但从一个城市到另一个城市的过程中不能穿过边界线.士兵有一个容量为K的背包装粮食,士兵到达一个城市可以选择攻占城市或者只是路过,如果 ...

  6. Loj 6002 最小路径覆盖(最大流)

    题意: 求不相交的最小路径覆盖 思路: 连边跑二分图,匹配一条边相当于缩了一条边,答案为n-maxflow 如果是求可以相交的最小路径覆盖的话,先用Floyd跑出可达矩阵,然后所有可达的点连边跑二分图 ...

  7. Light OJ 1429 Assassin`s Creed (II) BFS+缩点+最小路径覆盖

    题目来源:Light OJ 1429 Assassin`s Creed (II) 题意:最少几个人走全然图 能够反复走 有向图 思路:假设是DAG图而且每一个点不能反复走 那么就是裸的最小路径覆盖 如 ...

  8. [LOJ#6002]「网络流 24 题」最小路径覆盖

    [LOJ#6002]「网络流 24 题」最小路径覆盖 试题描述 给定有向图 G=(V,E).设 P 是 G 的一个简单路(顶点不相交)的集合.如果 V 中每个顶点恰好在 P 的一条路上,则称 P 是  ...

  9. POJ 2594 Treasure Exploration (可相交最小路径覆盖)

    题意 给你张无环有向图,问至少多少条路径能够覆盖该图的所有顶点--并且,这些路径可以有交叉. 思路 不是裸的最小路径覆盖,正常的最小路径覆盖中两个人走的路径不能有重复的点,而本题可以重复. 当然我们仍 ...

随机推荐

  1. Match:Milking Grid(二维KMP算法)(POJ 2185)

    奶牛矩阵 题目大意:给定一个矩阵,要你找到一个最小的矩阵,这个矩阵的无限扩充的矩阵包含着原来的矩阵 思路:乍一看这一题确实很那做,因为我们不知道最小矩阵的位置,但是仔细一想,如果我们能把矩阵都放在左上 ...

  2. codeforces 501C. Misha and Forest 解题报告

    题目链接:http://codeforces.com/problemset/problem/501/C 题目意思:有 n 个点,编号为 0 - n-1.给出 n 个点的度数(即有多少个点跟它有边相连) ...

  3. java判断身份证有效性

    import java.util.Calendar; public class CertNoUtil { public static boolean vIDNumByRegex(String idNu ...

  4. Linuxc:创建与监控多个子进程

    #include <unistd.h> #include <sys/types.h> #include <stdlib.h> #include <signal ...

  5. backBarButtonItem 替换

    最上级vc里面加 下级设置生效 UIImage* image = [UIImage imageNamed:@"back_button.png"]; [item setBackBut ...

  6. Android xml text 预览属性

    只在 AS 中生效 xmlns:tools="http://schemas.android.com/tools" tools:text="I am a title&quo ...

  7. NYOJ题目457大小写互换

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsUAAAIUCAIAAAB9y8bFAAAgAElEQVR4nO3dPW7bTNsG0G8T7r0Qt/

  8. 第一课 移动端&响应式

    一.调试工具介绍(Chrome Emulation) 1.Device(设备相关) 自定义尺寸.Network(网络模拟).UseAgent(浏览器信息).缩放 2.Media(媒体) 3.Netwo ...

  9. selenium--python如何定位一组元素并返回文本值

    from selenium import webdriverimport time a=[] #创建一个空列表用于存储查询到的元素组driver = webdriver.Firefox()driver ...

  10. HTTP1.0和HTTP1.1的主要区别是

    HTTP/.0协议使用非持久连接,即在非持久连接下,一个tcp连接只传输一个Web对象 HTTP/.1默认使用持久连接(然而,HTTP/.1协议的客户机和服务器可以配置成使用非持久连接)在持久连接下, ...