hdu3313 最大流找关键点,或者最短路找关键点.
题意:
给你一个有向图,然后给你起点和终点,问你从起点到终点有多少个关键点,如果当前的这个点删除了就无法从起点到终点,那么这个点就是一个关键点..
思路:
(1)有两种做法,我用的是最大流的,另一种是先跑最短路然后搜索,先说最大流,最大流的很容易理解,首先我们拆点建图,每个点拆成两个点,限流是1,然后起点和终点的限流是2,点于点之间是INF,跑一遍最大流,如果流量是0,说明不连接,那么所有的点都是关键点,输出n,如果流量是2那么说明最小割是2,也就是说无论你把那个点删除都不影响连通性,所以只有起点和终点是关键点,如果流量是1,那也就是说在路途中可能存在关键点,那么我们就
用暴力搜索的方式去找这些关键点,对于搜索这块我自己卡了两天了,今天才弄明白,首先我们定义跑完最大流后流量为0的边为关键边,首先第一个点一定是关键点,我们一个一个找,我的理解是 从当前的这个关键点出发,通过非关键边搜索,第一个搜索不到的点一定是关键点,这里的搜索不到的点指的是我们比如当前边u,v,他沿着非关键边无法从u走到v,但是沿着关键边可以走到,那么v就是第一个搜不到的点,v一定是关键点,跑完最大流后,流量0(正向)的是关键路径上的点,非0的是非关键路径上的点,我们每次从当前的关键点出发,沿着流量非0的跑,把这次跑到的点全记录下来,mark上,然后枚举每一个搜到的点相邻的点,如果是流量0,那么这个就是第一个到达不了的点,那么他一定是关键点,这届break,以这个点为起点在接着搜索,就这样一直找到T为止.还有为什么上面有两条边是2而不是别的,是为了缩短时间,2最多两次,我们是为了找到答案是0,1,还是其他,2.3.4..都是其他,都是只存在两个关键点的,所以我们要节省时间,流量2,如果弄大了答案肯定对,但会TLE...
最大流已知当前点找下一个关键点的搜索过程,红色是搜索路径,当前点a,下一个关键点是c,
则如图:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h>
#include<string.h>
#include<queue> #define N_node 200000 + 20
#define N_edge 600000 + 60
#define INF 1000000000
using namespace std; typedef struct
{
int to ,cost ,next;
}STAR; typedef struct
{
int x ,t;
}DEP; STAR E[N_edge];
DEP xin ,tou;
int list[N_node] ,tot;
int deep[N_node] ,list2[N_node];
int mark[N_node] ,num[N_node] ,tt; void add(int a, int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot; E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
} int minn(int x ,int y)
{
return x < y ? x : y;
} bool BFS(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
deep[s] = 0;
xin.x = s;
xin.t = 0;
queue<DEP>q;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
list2[i] = list[i];
return deep[t] != -1;
} int DFS_FLOW(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = list2[s] ;k; k = E[k].next)
{
list2[s] = k;
int to = E[k].to;
int cost = E[k].cost;
if(deep[to] != deep[s] + 1 || !cost) continue;
int tmp = DFS_FLOW(to ,t ,minn(cost ,flow - nowflow));
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(flow == nowflow)
break;
}
if(!nowflow) list2[s] = 0;
return nowflow;
} int DINIC(int s ,int t ,int n)
{
int sum = 0;
while(BFS(s ,t ,n))
{
sum += DFS_FLOW(s ,t ,INF);
}
return sum;
} void dfs(int s)
{
mark[s] = 1;
num[++tt] = s;
for(int k = list[s] ;k ;k = E[k].next)
{
int to = E[k].to;
if(E[k].cost && !mark[to])
dfs(to);
}
} int find(int n ,int S ,int T)
{
E[list[S]].cost = 0;
E[list[T - n]].cost= 0;
int cout = 0;
memset(mark ,0 ,sizeof(mark)); while(1)
{
tt = 0;
dfs(S);
int ok = 1;
for(int i = 1 ;i <= tt && ok ;i ++)
{
for(int k = list[num[i]] ;k && ok ;k = E[k].next)
if(k % 2 == 0 && !mark[E[k].to] && !E[k].cost)
{
ok = 0;
S = E[k].to;
cout ++;
if(E[k].to == T)
return cout;
}
}
}
} int main ()
{
int n ,m ,S ,T ,i ,j ,a ,b ,c;
while(~scanf("%d %d" ,&n ,&m))
{
memset(list ,0 ,sizeof(list));
tot = 1;
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d" ,&a ,&b);
add(a + n + 1,b + 1, INF);
}
scanf("%d %d" ,&S ,&T);
S ++ ,T ++;
for(i = 1 ;i <= n ;i ++)
{
if(i != S && i != T)
add(i ,i + n ,1);
else add(i ,i + n ,2);
}
T += n;
int flow = DINIC(S ,T ,n + n);
if(flow == 0) printf("%d\n" ,n);
else if(flow == 2) puts("2");
else printf("%d\n" ,find(n ,S ,T));
}
return 0;
}
思路:
(2)最短路,先跑一个最短路,记录路径,如果到不了T,那么就输出n,如果能的话,来一个深搜,看看只跑非最短路上的点能不能到达T,如果能,那么就说明至少存在两条不相交的路,那么直接输出2,否则就是存在关键点的情况了,枚举每一个关键点,通过非最短路上的点找到里关键点最远的那个最短路上的点,那么这个点一定是关键点,然后在吧当前的这个点当下一步的关键点,就这样一直找到T就行了..比最大流的那个好写,思路都差不多..
当前点a的下一个关键路径是c,是最远的那一个,如图.
#include<stdio.h>
#include<string.h>
#include<queue> #define N_node 110000
#define N_edge 330000
#define INF 1000000000
using namespace std; typedef struct
{
int to ,next ,cost;
}STAR; STAR E[N_edge];
int list[N_node] ,tot;
int mer[N_node] ,S ,T;
int s_x[N_node] ,mk_sx[N_node];
int mark[N_node]; void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot;
} bool SPFA(int s ,int t ,int n)
{
memset(mark ,0 ,sizeof(mark));
for(int i = 0 ;i <= n ;i ++)
{
s_x[i] = INF;
mer[i] = i;
}
s_x[s] = 0;
mark[s] = 1;
queue<int>q;
q.push(s);
while(!q.empty())
{
int xin ,tou;
tou = q.front();
q.pop();
mark[tou] = 0;
for(int k = list[tou] ;k ;k = E[k].next)
{
xin = E[k].to;
if(s_x[xin] > s_x[tou] + E[k].cost)
{
s_x[xin] = s_x[tou] + E[k].cost;
mer[xin] = tou;
if(!mark[xin])
{
mark[xin] = 1;
q.push(xin);
}
}
}
}
return s_x[t] != INF;
} int ok;
void DFS_1(int s)
{
for(int k = list[s] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to]|| ok) continue;
if(to == T) ok = 1;
if(mk_sx[to] || ok) continue;
mark[to] = 1;
DFS_1(to);
}
} int mk_id ,maxx;
void DFS_2(int s)
{
for(int k = list[s] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to]) continue;
if(mk_sx[to])
{
if(maxx < s_x[to])
{
maxx = s_x[to];
mk_id = to;
}
continue ;
}
mark[to] = 1;
DFS_2(to);
}
} int main ()
{
int n ,m ,i ,j;
int a ,b;
while(~scanf("%d %d" ,&n ,&m))
{
memset(list ,0 ,sizeof(list));
tot = 1;
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d" ,&a ,&b);
add(a + 1 ,b + 1 ,1);
}
scanf("%d %d" ,&S ,&T);
S ++ ,T ++;
if(!SPFA(S ,T ,n))
{
printf("%d\n" ,n);
continue;
}
memset(mk_sx ,0 ,sizeof(mk_sx));
int now = T;
while(mer[now] != now)
{
mk_sx[now] = 1;
now = mer[now];
}
mk_sx[now] = 1;
ok = 0;
memset(mark ,0 ,sizeof(mark));
mark[S] = 1;
DFS_1(S);
if(ok)
{
puts("2");
continue;
}
int sum = 1;
memset(mark ,0 ,sizeof(mark));
while(1)
{
//mk_id ,maxx
maxx = 0;
mark[S] = 1;
DFS_2(S);
sum ++;
S = mk_id;
//printf("%d***\n" ,S);
if(S == T) break;
}
printf("%d\n" ,sum);
}
return 0;
}
hdu3313 最大流找关键点,或者最短路找关键点.的更多相关文章
- 机器学习进阶-图像特征sift-SIFT特征点 1.cv2.xfeatures2d.SIFT_create(实例化sift) 2. sift.detect(找出关键点) 3.cv2.drawKeypoints(画出关键点) 4.sift.compute(根据关键点计算sift向量)
1. sift = cv2.xfeatures2d.SIFT_create() 实例化 参数说明:sift为实例化的sift函数 2. kp = sift.detect(gray, None) 找出 ...
- PTA L2-001 紧急救援-最短路(Dijkstra)多条最短路找最优解并输出路径 团体程序设计天梯赛-练习集
L2-001 紧急救援 (25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快 ...
- 前阿里CEO卫哲谈阿里创业经验:如何找人、找钱、找方向?(不同的阶段分别有:时间优先、金额优先、比例优先,不要做平台,太难)
新浪科技李根 整理报道 卫哲现在是御嘉基金的创始合伙人,他另一个更加知名的身份是阿里巴巴(B2B)前CEO,在2006年到2011年的时间里,卫哲见证了阿里巴巴如何利用人才.资本和方向选择一路壮大. ...
- IntelliJ IDEA 编译代码报错 找不到符号 符号: 找不到符号包 包
在使用IDEA的时候,经常出现过找不到包或者找不到符号的情况,可以尝试以下几种方式来解决 1.如果项目使用的是Maven可以使用Maven-Reimport 2.还可以 Invalidate and ...
- python找包的路径(找不到自定义包的问题解决)
问题:工程下自定义的包,python在执行时经常找不到包 python找包的路径:python安装路径下的lib包和PYTHONPATH下的包 可以使用[sys.path]打印出pytho ...
- Jenkins中,执行py文件,python找包的路径(找不到自定义包的问题解决)
问题:工程下自定义的包,python在执行时经常找不到包 python找包的路径:python安装路径下的lib包和PYTHONPATH下的包 可以使用[sys.path]打印出python找 ...
- IDEA 找不到包或者找不到符号的一些解决办法
有时使用IDE导入项目后,启动时会发生找不到包或者找不到符号的情况,下面有一些处理方法 1.右键项目Maven→Reimport 2.IDEA窗口左上角File→Invalidate and Rest ...
- poj 2135 Farm Tour 最小费用最大流建图跑最短路
题目链接 题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边:从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少? 思路 ...
- 最短路+找规律 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest L. Right Build
题目链接:http://codeforces.com/gym/101149/problem/L 题目大意:有n个点(其实是n+1个点,因为编号是0~n),m条有向边.起点是0,到a和b两个节点,所经过 ...
随机推荐
- 【DP】斜率优化初步
向y总学习了斜率优化,写下这篇blog加深一下理解. 模板题:https://www.acwing.com/problem/content/303/ 分析 因为本篇的重点在于斜率优化,故在此给出状态转 ...
- 手把手教你Spring Boot2.x整合Elasticsearch(ES)
文末会附上完整的代码包供大家下载参考,码字不易,如果对你有帮助请给个点赞和关注,谢谢! 如果只是想看java对于Elasticsearch的操作可以直接看第四大点 一.docker部署Elastics ...
- CloudQuery v1.3.4 版本更新
Hello,大家好久不见! 上一个版本(v1.3.3)发布已是春节前的事情了,此次 v1.3.4 是 CloudQuery 社区版在辛丑牛年的第一个版本发布.本次更新增加了新功能,优化了原有功能点.同 ...
- 基于CefSharp开发浏览器(九)浏览器历史记录弹窗面板
一.前言 前两篇文章写的是关于浏览器收藏夹的内容,因为收藏夹的内容不会太多,故采用json格式的文本文件作为收藏夹的存储方式. 关于浏览器历史记录,我个人每天大概会打开百来次网页甚至更多,时间越长历史 ...
- 如何在 C# 中使用 ArrayPool 和 MemoryPool
对资源的可复用是提升应用程序性能的一个非常重要的手段,比如本篇要分享的 ArrayPool 和 MemoryPool,它们就有效的减少了内存使用和对GC的压力,从而提升应用程序性能. 什么是 Arra ...
- 19. 一文搞懂 Go Modules 前世今生及入门使用
Hi,大家好. 我是明哥,在自己学习 Golang 的这段时间里,我写了详细的学习笔记放在我的个人微信公众号 <Go编程时光>,对于 Go 语言,我也算是个初学者,因此写的东西应该会比较适 ...
- 当红开发语言Go,真的是未来的技术主流吗?
摘要:文将详细介绍 Golang 的语言特点以及它的优缺点和适用场景,带着上述几个疑问,为读者分析 Go 语言的各个方面,以帮助初入 IT 行业的程序员以及对 Go 感兴趣的开发者进一步了解这个热门语 ...
- 从I/O多路复用到Netty,还要跨过Java NIO包
本文是Netty系列第4篇 上一篇文章我们深入了解了I/O多路复用的三种实现形式,select/poll/epoll. 那Netty是使用哪种实现的I/O多路复用呢?这个问题,得从Java NIO包说 ...
- D. 【例题4】字符串环
解析 字符串的操作,可以用函数解决这个问题 s 2. f i n d ( s 1. s u b s t r ( i , j ) ) s2.find~(s1.substr~(i,~j)) s2.find ...
- [状压DP]车
车 车 车 题目描述 在 n ∗ n n*n n∗n( n ≤ 20 n≤20 n≤20)的方格棋盘上放置 n n n个车(可以攻击所在行.列),有些格子不能放,求使它们不能互相攻击的方案总数. 输入 ...