题意:
     给你一个有向图,然后给你起点和终点,问你从起点到终点有多少个关键点,如果当前的这个点删除了就无法从起点到终点,那么这个点就是一个关键点..

思路:
     (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 最大流找关键点,或者最短路找关键点.相关推荐

  1. 程序员怎么找工作?程序员找工作越来越难怎么办?

    最近互联网大厂裁员的消息很多,直接原因还是来自于业绩压力.对于互联网公司而言,在外部公司空间增长猥琐的背景下.想要改善业绩,最直接到底方法还是裁员,所以很多人问,程序员怎么找工作?找工作越来越难怎么办 ...

  2. 只讲关键点之兼容100+种关键点检测数据增强方法

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨DefTruth 编辑丨极市平台 本文介绍了已有的几种关键点检测数据增强的方法,将其的优缺点进行 ...

  3. 软件测试是找BUG,不是找茬

            做测试久了,经常会有一些感悟,最近在51上看到一贴,说出了我的心声,把我一直想写却一直以时间为借口为由拖着未写的心声写出来,摘抄了部分过不,一起纪念测试的年代,测试的心声.测试好象一直 ...

  4. 由于找不到appvisvsubsystems32.dll_找茬游戏大全:我找东西贼快!小清新找茬游戏小程序,点开既玩...

    50000+游戏爱好者已加入我们! 每天推荐好玩游戏! 关注我们,沐沐带你发现好游戏! <我找东西贼快>游戏小程序好玩吗? <我找东西贼快>小游戏怎么玩? 怎么进入<我找 ...

  5. python怎么找出最大数,python怎么找出最大数

    python怎么找出最大数,表达式,参数,数值,方法,大数 python怎么找出最大数 易采站长站,站长之家为您整理了python怎么找出最大数的相关内容. python怎么找出最大数? python ...

  6. 打官司除了找律师,还能找谁?

    转自:http://wenzhang.ztcztc.com/Detail.aspx?id=3A4038EE-76CC-5085-993A-20898E017518 我要逃离北上广! 虽然北上广有灯红酒 ...

  7. 程序员年底失业,到底是该年前找工作好还是年后找工作好?

    最近在网上看见大家讨论的比较多的话题:"2020年快结束了,如果年底失业,到底是该年前找工作好还是年后找工作好?" 其实我对于这个话题的观点是年前找工作比较好. 为什么呢? 首先因 ...

  8. linux系统重启后找不到硬盘,戴尔电脑重装系统后找不到硬盘或找不到引导设备怎么办?...

    [文章导读]戴尔电脑是一款不的品牌,戴尔电脑一直以来都是以IT直销享誉全球的.而旗下的戴尔台式机和笔记本,更是深受用户们的追捧和喜爱.2016年以前我们重装戴尔笔记本系统比较简单可以用U盘或硬盘安装方 ...

  9. 积米:化妆找吉米,逛街找积米

    要化妆找吉米,要购物找积米.移动端与位置结合的应用目前有两大热门方向,一个是社交,一个是周边生活服务信息,积米就是属于后一种.它是以购物为主,提供周边商场及品牌的信息.活动.打折等.用户可以根据某一品 ...

最新文章

  1. 看linux书籍做的一些重要笔记(2011.07.03更新)
  2. 南农Nature Microbiology一作顾少华:我与铁载体的这5年
  3. python的__new__方法和__del__方法
  4. QUIC实战(一) 通过Quiche部署支持HTTP3 的NGINX
  5. iframe的src怎么携带参数_三种传递gRPC动态参数方式的使用体验
  6. ssm异常捕获和处理
  7. 谁参加了JavaScript 2018状况调查?
  8. 求4个数字组成的不重复三位数,Python简洁解法
  9. Numpy | Python列表与Numpy数组对比
  10. css定位能用android,绝对的CSS定位显示android html上的空白区域
  11. it项目经理成长手记 mobi_步入IT行业的心路历程
  12. mysql数据迁移到sqlserver_技术分享 | 使用OGG实现Oracle到MySQL数据平滑迁移
  13. qml之TextArea 添加滚动条
  14. python文件写入乱码_python2写入文件乱码怎么解决?
  15. 图像识别技术原理和神经网络的图像识别技术
  16. B端、C端产品的区别|产品经理面试题第1篇|||答题思路
  17. JS 根据date日期格式返回周几
  18. 上楼梯(递归和迭代的对比)
  19. 输入网址自动跳转到域名纠错系统-解决办法:(北京网通:现在称为垃圾廉通)...
  20. 悍将余承东「调防」,华为云能翻盘吗?

热门文章

  1. Windows service无法删除怎么办?
  2. jQuery 3.0的domManip浅析
  3. 关于Yii2中CSS,JS文件的引入心得
  4. 高级Java服务端工程师要求
  5. Tomcat 6.0 日志处理
  6. ASP.NET 网站路径[转载]
  7. 1209F - Koala and Notebook
  8. request对象中的get、post方法
  9. jQuery Layer 弹层组件
  10. 未处理的异常: 0xC0000235: 由句柄所调用的 NtClose 已使用 NtSetInformationObject 以防止关闭。...