题目大意:https://www.cnblogs.com/Juve/articles/11226266.html

题解:

感觉挺水的,但考场上没打出来

题目翻译一下就是输出起点到终点必经的点

其实就是求起点到终点的割点

这题算法非常多,我介绍我的方法:

55%:

可能这个算法是不严谨的,但至少能那55分

我们先tarjan求点双,然后缩点

然后我们从1号点所在点双开始dfs,

维护一个栈,每到一个点双,就把点双中的割点压入栈里,继续搜索

回溯时在弹栈,当我们搜到n号点所在点双,就停止搜索

这样栈中剩余的点就是我们要求的点

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<stack>
#define MAXM 4000005
#define MAXN 2000005
#define ll long long
#define re register
using namespace std;
inline ll read(){
re ll x=0;char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x;
}
ll t,n,m;
ll to[MAXM<<2],nxt[MAXM<<2],pre[MAXN],cnt=0;
inline void add(re ll u,re ll v){
cnt++,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
}
ll ver[MAXM<<2],nxtt[MAXM<<2],head[MAXN],sum=0;
inline void ADD(re ll u,re ll v){
sum++,ver[sum]=v,nxtt[sum]=head[u],head[u]=sum;
}
ll dfn[MAXN],low[MAXN],dfs_order=0,sta[MAXN],top=0,dcc_num=0,belong[MAXN];
bool is_cut[MAXN];
vector<ll>dcc[MAXN];
inline void tarjan(re ll x){
dfn[x]=low[x]=++dfs_order;
sta[++top]=x;
ll num=0;
for(re ll i=pre[x];i;i=nxt[i]){
re ll y=to[i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
num++,dcc_num++;
if(x!=1||num>1) is_cut[x]=1;
re ll z;
do{
z=sta[top--];
dcc[dcc_num].push_back(z);
}while(y!=z);
dcc[dcc_num].push_back(x);
}
}
else low[x]=min(low[x],dfn[y]);
}
}
stack<ll>a;
ll tot=0,num=0,new_id[MAXN];
bool flag=0,ans[MAXN];
void dfs(ll x,ll fa){
if(x==belong[n]){
flag=1;
return ;
}
for(ll i=head[x];i;i=nxtt[i]){
if(ver[i]==fa) continue;
ll y=ver[i],N=dcc[y].size();
for(ll j=0;j<N;j++){
if(is_cut[dcc[y][j]]){
//cout<<dcc[y][j]<<endl;
a.push(dcc[y][j]);
}
}
dfs(y,x);
if(flag) return ;
}
//cout<<a.top()<<endl;
if(!a.empty()) a.pop();
}
signed main(){
t=read();
while(t--){
n=read(),m=read();
for(re ll i=1,u,v;i<=m;i++){
u=read(),v=read();
if(u==v) continue;
add(u,v),add(v,u);
}
tarjan(1);
num=dcc_num;
for(re ll i=1;i<=n;i++)
if(is_cut[i]) new_id[i]=++num;
for(re ll i=1;i<=dcc_num;i++){
re ll N=dcc[i].size();
for(re ll j=0;j<N;j++){
re ll t=dcc[i][j];
if(is_cut[t]){
ADD(i,new_id[t]);
ADD(new_id[t],i);
belong[t]=new_id[t];
}else belong[t]=i;
}
}
//for(ll i=1;i<=n;i++)
// cout<<i<<' '<<belong[i]<<endl;
//cout<<"------------------------"<<endl;
//for(ll i=1;i<=num;i++){
// for(ll j=head[i];j;j=nxtt[j]){
// cout<<i<<' '<<ver[j]<<endl;
// }
//}
dfs(belong[1],0);
while(!a.empty()){
re ll tp=a.top();
a.pop();
if(!ans[tp]){
if(tp!=1&&tp!=n){
ans[tp]=1;
tot++;
}
}
}
printf("%lld\n",tot);
for(ll i=2;i<n;i++)
if(ans[i])
printf("%lld ",i);
puts("");
memset(pre,0,sizeof(pre));
cnt=dfs_order=tot=dcc_num=sum=num=0;
memset(dfn,0,sizeof(dfn));
memset(is_cut,0,sizeof(is_cut));
memset(dcc,0,sizeof(dcc));
memset(head,0,sizeof(head));
memset(ans,0,sizeof(ans));
flag=0;
}
return 0;
}
/*
15 19
1 2
1 3
1 12
12 13
13 14
12 14
2 4
3 4
4 6
4 5
6 5
5 7
5 8
7 8
7 9
8 9
9 15
15 11
15 10 4 3
1 2
2 3
3 4 5 5
1 2
2 3
3 4
4 5
4 1 5 5
1 2
2 3
3 4
4 5
5 1
*/

这有什么问题吗?为什么一直55分?有大佬能解释的话可以留言

另一种算法:

这个算法一直90分,但找不到问题(是某大佬提出的)

我们用dijkstra或spfa跑1到n的最短路,顺便记录路径

那么必经点一定在这条路上

那么我们就可以求桥,桥两边的点都是要求的点

100%:

其实只要在tarjan就割点的板子上加一句话就A了:

在判割点时,在判断条件后加上dfn[to[i]]<=dfn[n]就可以了

 if(low[y]>=dfn[x]&&dfn[y]<=dfn[n]){
num++;
if(x!=||num>) is_cut[x]=,tot++;
}

想一下tarjan的实现原理,dfn[n]是终点的dfn值

我们发现如果一个节点y的dfn值大于n,那么n肯定优先于y被搜到,

而我们是从1开始dfs,所以y肯定不在1到n的必经路上

那么这道题就非常水了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define MAXM 400005
#define MAXN 200005
#define ll long long
#define re register
using namespace std;
inline ll read(){
re ll x=0;char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x;
}
ll t,n,m;
ll to[MAXM<<1],nxt[MAXM<<1],pre[MAXN],cnt=0;
inline void add(re ll u,re ll v){
cnt++,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
}
ll dfn[MAXN],low[MAXN],dfs_order=0,tot=0;
bool is_cut[MAXN];
inline void tarjan(re ll x){
dfn[x]=low[x]=++dfs_order;
re ll num=0;
for(re ll i=pre[x];i;i=nxt[i]){
re ll y=to[i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]&&dfn[y]<=dfn[n]){
num++;
if(x!=1||num>1) is_cut[x]=1,tot++;
}
}
else low[x]=min(low[x],dfn[y]);
}
}
signed main(){
t=read();
while(t--){
n=read(),m=read();
for(re ll i=1,u,v;i<=m;i++){
u=read(),v=read();
if(u==v) continue;
add(u,v),add(v,u);
}
tarjan(1);
printf("%lld\n",tot);
for(re ll i=1;i<=n;i++){
if(is_cut[i])
printf("%lld ",i);
}
puts("");
cnt=dfs_order=tot=0;
memset(pre,0,sizeof(pre));
memset(dfn,0,sizeof(dfn));
memset(is_cut,0,sizeof(is_cut));
}
return 0;
}

再来一道loj上类似的题:ZJOI 2004「一本通 3.6 练习 2」嗅探器https://loj.ac/problem/10101

你会发现这道题非常水,只不过起点终点不是1和n了

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#define MAXM 2005
#define MAXN 1005
#define ll long long
#define re register
using namespace std;
ll a, b, n, u, v, ans = 0x7fffffff;
ll to[MAXM << 1], nxt[MAXM << 1], pre[MAXN], cnt = 0;
inline void add(re ll u, re ll v) { cnt++, to[cnt] = v, nxt[cnt] = pre[u], pre[u] = cnt; }
ll dfn[MAXN], low[MAXN], dfs_order = 0, tot = 0;
bool is_cut[MAXN];
inline void tarjan(re ll x) {
dfn[x] = low[x] = ++dfs_order;
re ll num = 0;
for (re ll i = pre[x]; i; i = nxt[i]) {
re ll y = to[i];
if (!dfn[y]) {
tarjan(y);
low[x] = min(low[x], low[y]);
if (low[y] >= dfn[x] && dfn[y] <= dfn[b]) {
num++;
if (x != a || num > 1)
tot++, ans = min(ans, x);
}
} else
low[x] = min(low[x], dfn[y]);
}
}
signed main() {
scanf("%lld", &n);
while (~scanf("%lld%lld", &u, &v)) {
if (u + v == 0)
break;
add(u, v), add(v, u);
}
scanf("%lld%lld", &a, &b);
tarjan(a);
if (tot)
printf("%lld\n", ans);
else
puts("No solution");
return 0;
}

HZOI20190725 B 回家 tarjan的更多相关文章

  1. NOIP 模拟七 考试总结

    T1匹配 签到大水题,这里有hash,kmp,ac自动机,还有后缀数组,后缀自动机任您挑选. 不过这个数据范围有些坑啊,re就很不爽.做法我还是比较倾向hash的,毕竟不论神魔字符算法,hash大都能 ...

  2. 【模拟7.25】回家(tarjan V-DCC点双连通分量的求法及缩点 求割点)模板题

    作为一道板子题放在第二题令人身心愉悦,不到一个小时码完连对拍都没打. 关于tarjan割点的注意事项: 1.在该板子中我们求的是V-DCC,而不是缩点,V-DCC最少有两个点组成,表示出掉一个块里的任 ...

  3. hihoCoder 1185 连通性·三(Tarjan缩点+暴力DFS)

    #1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...

  4. 2-sat(tarjan算法)hdu(1824)

    hdu1824 Let's go home Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...

  5. HDU 1824 Let's go home(2-SAT+Tarjan)

    Let's go home Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  6. noip模拟7[匹配·回家·寿司]

    这次考试状态好像还是没有回来,只拿了55pts,还全是第一题的功劳,就是一个小KMP,然后还让我给打错了 就很难受,while打成了if,然后wa掉45分考完立马拿回来了,悔死了,害 第二题爆零了,为 ...

  7. NOIP模拟测试8「匹配·回家」

    匹配 哈希能A 水到爆炸 回家 事实上我做过一个原题,甚至比这个回家难的多,而且那个题多组询问必经点 然后我做一组询问就打炸了 大约就是删了很多东西,然后自己想的太简单了 直接统计了割点,懒得打lca ...

  8. flhs笔试题-回家上机实践

    这是最近参加的一个公司的笔试题,回家上机写了下代码,希望对有需要的小伙伴有用,简单实现字符串和数组在指定位置的插入: package org.flhs; import com.google.commo ...

  9. 三石推荐!把 Bootstrap 小清新带回家!

    无敌传送门:http://fineui.com/demo_pro/default.aspx?theme=bootstrap1&menu=accordion   喜欢就来赞一个! 把麻烦留给三石 ...

随机推荐

  1. [转] undefined reference to `clock_gettime'

    下面这个错误通常是因为链接选项里漏了-lrt,但有时发现即使加了-lrt仍出现这个问题,使用nm命令一直,会发现-lrt最终指向的文件 没有包含任何symbol,这个时候,可以找相应的静态库版本lib ...

  2. 记录一次失败的向git提交代码,和解决的方法。(首次创建仓库)

    背景: 向git push代码(创建一个新的仓库) 做法: 在github创建一个新的仓库------>本地新建文件夹------->依次执行了下面的命令 git init git clo ...

  3. AT指令集之Call

    1.//unsolicited result code,URC表示BP->AP+ESIPCPI:<call_id>,<dir>,<sip_msg_type>, ...

  4. 46张PPT弄懂JVM、GC算法和性能调优!

    来源:cnblogs.com/cyfonly/p/5807121.html 本PPT从JVM体系结构概述.GC算法.Hotspot内存管理.Hotspot垃圾回收器.调优和监控工具六大方面进行讲述. ...

  5. 数据库MySQL--数据操作语言DML(插入、修改、删除)

    例子文件:https://files-cdn.cnblogs.com/files/Vera-y/girls.zip 一.插入 方式一: 语法: insert into 表名(列名,.....) val ...

  6. mui--使用mui中的图文表格组件时出现一条横线的解决方法

    最近做的微信公众号点击链接跳转到H5页面,该H5页面使用mui做的,遇到的商品列表页出现一个横线的问题, 这个是修改前的图片 解决方法: <style type="text/css&q ...

  7. mysql Slave 启动失败

    报错日志 Slave failed to initialize relay log info structure java程序访问日志显示事物查询失败,排查mysql 发现其中一台slave 启动状态 ...

  8. 【JZOJ6370】基础 fake 练习题

    description 装饰者坐在树荫下听着长者讲述以前的故事: 大神 yk 非常喜欢树,便钦点班里的 n 个小蒟蒻站在一棵 n 个点以 1 为根的树上,并且每个点上恰好有 1 个小蒟蒻. 大神 yk ...

  9. 8-5接口测试用例设计与编写2 rest-assured

    rest-assured 简约的接口测试DSL 支持xml json的结构化解析 支持xpath jsonpath gpath等多种解析方式 对Spring的支持比较前面 底层是httpclient ...

  10. cocos2D-X LUA 常用功能封装和工作经验的一些解决方案

    --[[ Packaging_KernelEngine.h 文件说明:所有对象在建立时位置是优先的,传入位置参数必须cc.p(X,Y) CurObj:表示要传入当前的对象 将3.10 lua api ...