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 (可相交最小路径覆盖)
题意 给你张无环有向图,问至少多少条路径能够覆盖该图的所有顶点--并且,这些路径可以有交叉. 思路 不是裸的最小路径覆盖,正常的最小路径覆盖中两个人走的路径不能有重复的点,而本题可以重复. 当然我们仍 ...
随机推荐
- android studio Error:java.lang.OutOfMemoryError: GC overhead limit exceeded
android studio Error:java.lang.OutOfMemoryError: GC overhead limit exceeded 在app下的build.gradle中找到and ...
- ECharts分析xdebug跟踪日志
2015年12月23日 15:36:11 星期三 之前用的是国外的图表工具, 有点麻烦, 文档是英文的, 看着不顺眼, 发现了百度出品的ECharts, 文档比较全, 功能比较多, 做出的图也比较好看 ...
- ffmpeg-20160517-git-bin-v2
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...
- suse linux 10 下配置vpn服务器(pptp)
一.安装所需的软件包: pptpd-*.rpm ppp-*.rpm pptp-*.rpm 一般情况下系统已经将pptp和ppp包安装好了,所以只需安装pptpd ...
- Effective C++ -----条款17:以独立语句将newed对象置入智能指针
以独立语句将newed对象存储于(置入)智能指针内.如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄露.
- WebService及WCF获取客户端IP,端口
wcf获取客户端IP,端口 var context = OperationContext.Current; var properties = context.IncomingMessageProper ...
- EF-实体更新
1.数据库表增加字段,EF更新视图后,对应的实体对象没有新增的字段原因:edmx文件右键属性设置了 保存时转换相关的文本模板-false...正确的应该是rue 2. 更改视图后(或者更改字段类型?) ...
- ibatis中使用like模糊查询
select * from table1 where name like '%#name#%' 两种有效的方法: 1) 使用$代替#.此种方法就是去掉了类型检查,使用字符串连接,不过可能会有sql注入 ...
- objective-c字符串笔记
字符串 // 字符串 分可变字符串和不可变字符串 // 不可变字符串的初始化方式 // NSString *string = [[NSString allo ...
- self dismissModalViewControllerAnimated:YES 无效(dismissviewcontrolleranimated无效)
作为一个viewController(VC),想要消失的时候可以从parent VC里面调用dismissModalViewControllerAnimated来消去改VC,也可以在该VC里面手动调用 ...