今天几道是模板题;

第一道:(粘不了链接呜呜呜)

题目描述

n个城市之间有通讯网络,每个城市都有通讯交换机,直接或间接与其它城市连接。因电子设备容易损坏,需给通讯点配备备用交换机。

但备用 交换机数量有限,不能全部配备,只能给部分重要城市配置。

于是规定:如果某个城市由于交换机损坏,不仅本城市通讯中断,还造成其它城市通讯中断,则配备备 用交换机。

请你根据城市线路情况,计算需配备备用交换机的城市个数,及需配备备用交换机城市的编号。

友情提示:图论常见的坑点,重边,自环,还有对本题来说的不连通

输入格式

第一行,一个整数n,表示共有n个城市(2<=n<=20000)

下面有若干行(<=60000):每行2个数a、b,a、b是城市编号,表示a与b之间有直接通讯线路。

输出格式

第一行,1个整数m,表示需m个备用交换机。

下面有m行,每行有一个整数,表示需配备交换机的城市编号。

输出顺序按编号由小到大。如果没有城市需配备备用交换机则输出0。

题解:对于中心交换器a,b;只需以a为根节点进行遍历,寻找割点的子树中是否含有b节点;如果有,则是一种可行解;

#include<bits/stdc++.h>
using namespace std;
#define N 500001
struct gg
{
int y,next;
}a[N];
inline int read()
{
int x=,f=;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ch=-;ch=getchar();}
while(isdigit(ch)) {x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;
}
int n,m,ans[N<<],lin[N<<],tot,cnt,dfn[N<<],low[N<<];
int root;
inline void add(int x,int y)
{
a[++tot].y=y;
a[tot].next=lin[x];
lin[x]=tot;
}
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
int flag=;
for(int i=lin[x];i;i=a[i].next)
{
int y=a[i].y;
if(!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
flag++;
if(x!=root||flag>) ans[x]=;
}
}
else low[x]=min(low[x],dfn[y]);
}
}
int main()
{
freopen("gd.in","r",stdin);
freopen("gd.out","w",stdout);
n=read();
tot=;
memset(dfn,,sizeof(dfn));
memset(lin,,sizeof(lin));
memset(low,,sizeof(low));
memset(ans,,sizeof(ans));
int x,y;
while(scanf("%d%d",&x,&y)!=EOF)
{
if(x==y) continue;
add(x,y);add(y,x);
}
for(int i=;i<=n;i++)
if(dfn[i]==) root=i,tarjan(i);
int k=;
for(int i=;i<=n;i++)
if(ans[i]) ++k;
cout<<k<<endl;
for(int i=;i<=n;i++)
if(ans[i]) cout<<i<<endl;
return ;
}

第二题:LUOGU5058

摘自:https://www.luogu.org/blog/da32s1da/solution-p5058

首先非常明显的是,只能把服务器建在割点上,因为只有这样,才能捕获到全部的数据。

考虑如何求x,y两点之间的必经的割点。

很明显需要满足4个条件

考虑我们有一个u点,它连了一个v点,那么u点需要满足4个条件。

  1. u不是起点终点。因为题目要求在中间服务器上建嗅探器。
  2. u是割点。
  3. 终点(y)的dfn应该大于等于v点的dfn,因为要确保终点在v点或之后被访问到,即u点为必经的点。
  4. 终点(y)的low应该大于等于u点的dfn,因为要确保终点必须要经过u点。

剩下的没什么了,板子

注意我们从x点开始tarjan,就不用看x点是不是割点了。

#include<bits/stdc++.h>
using namespace std;
#define N 500001
inline int read()
{
int x=,f=;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;
}
int n,m,tot,lin[N],dfn[N],low[N],k,cnt,root,x,y;
int ans=0x7fffffff;
struct gg
{
int y,next;
}a[N<<];
void add(int x,int y)
{
a[++tot].y=y;
a[tot].next=lin[x];
lin[x]=tot;
}
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
for(int i=lin[u];i;i=a[i].next)
{
int v=a[i].y;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(u!=x&&u!=y)
if(dfn[u]<=low[v]&&dfn[v]<=dfn[y]&&low[y]>=dfn[x])
ans=min(ans,u);
}
else low[u]=min(low[u],dfn[v]);
}
}
int main()
{
n=read();
memset(dfn,,sizeof(dfn));
memset(lin,,sizeof(lin));
while(cin>>x>>y&&x!=&&y!=)
add(x,y),add(y,x);
x=read();y=read();
tarjan(x);
if(ans!=0x7fffffff) cout<<ans<<endl;
else cout<<"No solution"<<endl;
return ;
}

第三题:LUOGU P3469

#include<bits/stdc++.h>
using namespace std;
#define N 500001
inline int read()
{
int x=,f=;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;
}
int lin[N],dfn[N],low[N],tot,n,m,x,y,cnt,size[N],cut[N];
long long ans[N];
struct gg
{
int y,next;
}a[N<<];
void add(int x,int y)
{
a[++tot].y=y;
a[tot].next=lin[x];
lin[x]=tot;
}
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
size[x]=;
int flag=,sum=;
for(int i=lin[x];i;i=a[i].next)
{
int y=a[i].y;
if(!dfn[y])
{
tarjan(y);
size[x]+=size[y];
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
flag++;
ans[x]+=(long long)size[y]*(n-size[y]);
sum+=size[y];
if(x!=||flag>) cut[x]=;
}
}
else low[x]=min(low[x],dfn[y]);
}
if(cut[x]) ans[x]+=(long long)(n-sum-)*(sum+)+(n-);
else ans[x]=*(n-);
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
n=read();m=read();
tot=;
for(int i=;i<=m;i++)
{
int x,y;
x=read();y=read();
if(x==y) continue;
add(x,y),add(y,x);
}
tarjan();
for(int i=;i<=n;i++)
printf("%lld\n",ans[i]);
return ;
}

第四题:

题目描述

天凯是苏联的总书记。苏联有n个城市,某些城市之间修筑了公路。任意两个城市都可以通过公路直接或者间接到达。 天凯发现有些公路被毁坏之后会造成某两个城市之间无法互相通过公路到达。这样的公路就被称为dangerous pavement。 为了防止美帝国对dangerous pavement进行轰炸,造成某些城市的地面运输中断,天凯决定在所有的dangerous pavement驻扎重兵。可是到底哪些是dangerous pavement呢?你的任务就是找出所有这样的公路。

输入格式

第一行n,m(1<=n<=100000, 1<=m<=300000),分别表示有n个城市,总共m条公路。

以下m行每行两个整数a, b,表示城市a和城市b之间修筑了直接的公路。

输出格式

输出有若干行。每行包含两个数字a,b(a < b),表示 < a,b >是dangerous pavement。请注意:输出时,所有的数对< a,b>必须按照a从小到大排序输出;如果a相同,则根据b从小到大排序。

寻找割边输出,最后输出处理一下,并且保证题目要求的顺序;

#include<bits/stdc++.h>
using namespace std;
#define N 500001
inline int read()
{
int x=,f=;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;
}
struct gg
{
int y,next;
}a[N<<];
struct pink
{
int x,y;
}b[N<<];
bool mycmp(pink a,pink b)
{
if(a.x!=b.x) return a.x<b.x;
else return a.y<b.y;
}
int lin[N*],dfn[N*],low[N*],tot,cnt,n,m,x,y,bridge[N*];
inline void add(int x,int y)
{
a[++tot].y=y;
a[tot].next=lin[x];
lin[x]=tot;
}
inline void tarjan(int x,int in_edge)
{
dfn[x]=low[x]=++cnt;
for(int i=lin[x];i;i=a[i].next)
{
int y=a[i].y;
if(!dfn[y])
{
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x])
bridge[i]=bridge[i^]=;
}
else if(i!=(in_edge^))
low[x]=min(low[x],dfn[y]);
}
}
int main()
{
freopen("danger.in","r",stdin);
freopen("danger.out","w",stdout);
n=read();m=read();
memset(lin,,sizeof(lin));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
tot=;
for(int i=;i<=m;i++)
{
x=read();y=read();
add(x,y);add(y,x);
}
for(int i=;i<=n;i++)
if(dfn[i]==) tarjan(i,);
int k=;
for(int i=;i<=tot;i+=)
if(bridge[i])
{
k++;
if(a[i].y<a[i^].y)
b[k].x=a[i].y,b[k].y=a[i^].y;
else b[k].x=a[i^].y,b[k].y=a[i].y;
}
sort(b+,b++k,mycmp);
for(int i=;i<=k;i++)
cout<<b[i].x<<' '<<b[i].y<<endl;
return ;
}

第五题:luoguP1726

#include<bits/stdc++.h>
#define N 100500
using namespace std;
template<typename T>inline void read(T &x)
{
x=;
register int f=;
register char ch=getchar();
while (!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while (isdigit(ch)) x=(x<<)+(x<<)+(ch^), ch=getchar();
x*=f;
}
struct gg
{
int next,y;
}e[N<<];
int lin[N<<],dfn[N],low[N],cnt,tot,hl,n,m,ans[N];
int du[N],id[N],all[N];
bool v[N];
stack<int>s;
inline void add(int x,int y)
{
cnt++;
e[cnt].y=y;
e[cnt].next=lin[x];
lin[x]=cnt;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
s.push(x);v[x]=true;
for(int i=lin[x];i;i=e[i].next)
{
int u=e[i].y;
if(!dfn[u])
{
tarjan(u);
low[x]=min(low[x],low[u]);
}
else if(v[u]) low[x]=min(low[x],dfn[u]);
}
int k;
if(low[x]==dfn[x])
{
++hl;
do
{
k=s.top();s.pop();
v[k]=false;
id[k]=hl;all[hl]++;
}while(x!=k);
}
}
int main()
{
freopen("classroom.in","r",stdin);
freopen("classroom.out","w",stdout);
read(n);read(m);
int a,b,c;
for(int i=;i<=m;i++)
{
read(a);read(b);read(c);add(a,b);
if(c==) add(b,a);
}
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
int t=,dcc;
for(int i=;i<=hl;i++)
{
if(t<all[id[i]])
{dcc=i;t=all[id[i]];}
}
cout<<t<<endl;
int k=;
for(int j=;j<=n;j++)
{
if(id[j]==id[dcc])
ans[++k]=j;
}
cout<<ans[];
for(int i=;i<=k;i++)
cout<<' '<<ans[i];
return ;
}

D7 割点 割边 强连通分量的更多相关文章

  1. POJ1523 Tarjan求割点以及删除割点之后强连通分量的数量

    题目链接:http://poj.org/problem?id=1523 SPF:A Single Point of Failure也就是割点(一个点导致网络之间的不连通),由于给出的图是无向图,所以只 ...

  2. 【学习整理】Tarjan:强连通分量+割点+割边

    Tarjan求强连通分量 在一个有向图中,如果某两点间都有互相到达的路径,那么称中两个点强联通,如果任意两点都强联通,那么称这个图为强联通图:一个有向图的极大强联通子图称为强联通分量.   算法可以在 ...

  3. tarjan算法(割点/割边/点连通分量/边连通分量/强连通分量)

    tarjan算法是在dfs生成一颗dfs树的时候按照访问顺序的先后,为每个结点分配一个时间戳,然后再用low[u]表示结点能访问到的最小时间戳 以上的各种应用都是在此拓展而来的. 割点:如果一个图去掉 ...

  4. tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)

    这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...

  5. Tarjan 强连通分量 及 双联通分量(求割点,割边)

    Tarjan 强连通分量 及 双联通分量(求割点,割边) 众所周知,Tarjan的三大算法分别为 (1)         有向图的强联通分量 (2)         无向图的双联通分量(求割点,桥) ...

  6. 小结:双连通分量 & 强连通分量 & 割点 & 割边

    概要: 各种dfs时间戳..全是tarjan(或加上他的小伙伴)无限膜拜tarjan orzzzzzzzzz 技巧及注意: 强连通分量是有向图,双连通分量是无向图. 强连通分量找环时的决策和双连通的决 ...

  7. Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】

    一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...

  8. (转)Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)

    基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...

  9. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

随机推荐

  1. 进程锁Lock

    例1: 10个人去买票,先去查询余票,有票就去购买.代码如下: # ticket.py {"ticket": 1} # 只有一张票 import json import time ...

  2. VUE组件的学习

    参考:https://blog.csdn.net/baidu_23142899/article/details/79130225

  3. 如何开始学习ADF和Jdeveroper 11g

    作为第一篇博客,先给一些资料可以帮助初学者开始学习ADF和Jdeveloper11g 1.首先毫无疑问,你要懂java语言, 可以看看Thinking In Java, 或者原来sun的网上的一些文档 ...

  4. asp.net session锁导致ajax请求阻塞

    问:为了可以顺序访问Session的状态值,Session是否提供了锁定机制?答:Session实现了Reader/Writer的锁机制:当页面对Session具有可写功能(即页面有<%@Pag ...

  5. python全栈开发 * 29知识点汇总 * 180712

    29 正则表达式 re模块一.正则表达式官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”, 这个“规则字符串”用来表达对字 ...

  6. JavaScript基础知识(函数)

    函数的基础 函数: 把实现相同功能的代码放到一个函数体中,当想实现这个功能时,直接执行这个函数即可:减少了的冗余:高内聚,低耦合--> 函数的封装: 函数:引用数据类型: var a = 10; ...

  7. 20175320 2018-2019-2 《Java程序设计》第3周学习总结

    20175320 2018-2019-2 <Java程序设计>第3周学习总结 教材学习内容总结 本周学习了教材的第四章的内容.在这章中介绍了面向对象编程的概念以及Java编程中的类与对象, ...

  8. Golang自定义包导入

    # 文件Tree project -/bin -/pkg -/src -main.go -/test -test1.go -test2.go main.go package main import ( ...

  9. MySQL优化小结

    数据库的配置是基础.SQL优化最重要(贯穿始终,每日必做),由图可知,越往上优化的面越小,最基本的SQL优化是最重要的,往上各个参数也没太多调的,也不可能说调一个innodb参数性能就会好多少,而动不 ...

  10. PHP实现数组中每个字符出现次数最多的,并且如果两个字符出现相同,则在前面的先输出功能

    $arr = ['a', 'b', 'a', 'e', 'g', 'g', 'a']; $count_per_values = array_count_values($arr); $res = []; ...