今天几道是模板题;

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

题目描述

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. Let's Encrypt泛域名SSL证书申请

    操作系统:CentOS 7 github:https://github.com/Neilpang/acme.sh 有中文说明: https://github.com/Neilpang/acme.sh ...

  2. web.py框架之i18n支持

    问题: 在web.py的模板文件中, 如何得到i18n的支持? Solution: 项目目录结构: proj/ |- code.py |- i18n/ |- messages.po |- en_US/ ...

  3. 对于input 框限定输入值为正整数,浮点型的js

    <input type="text" value="" onkeyup="only_num(this)" onblur="o ...

  4. selenium+python爬虫环境搭建

    前言: 准备使用selenium爬取网站数据,先搭建selenium+python爬虫环境搭建 系统环境: 64位win10系统,同时装python2.7和python3.6两个版本,IDE为pych ...

  5. python学习之旅(五)

    Python基础知识(4):基础数据类型之字符串(Ⅰ) 字符串是 Python 中最常用的数据类型.可以使用引号“ ”来创建字符串,只要为变量分配一个值即可.例如: name=“Alice” 注:字符 ...

  6. POJ 3279 - Fliptile - [状压+暴力枚举]

    题目链接:http://poj.org/problem?id=3279 Sample Input 4 4 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1 Sample Output 0 ...

  7. 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types

    匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...

  8. Eclipse 00: 常用快捷键

    Eclipse常用快捷键 1几个最重要的快捷键 代码助手:Ctrl+Space(简体中文操作系统是Alt+/)快速修正:Ctrl+1单词补全:Alt+/打开外部Java文档:Shift+F2 显示搜索 ...

  9. I2C驱动框架 (kernel-3.4.2)

    先用韦老师的图: 注:  新版本内核的i2c驱动框架采用了    i2c_client -------> i2c_bus_type  <-------- i2c_driver   框架 如 ...

  10. 【托业】【新东方托业全真模拟】TEST09~10-----P5~6

    at no time 绝不,从不 takeover 收购 startup n.启动; 新兴公司(尤指新兴网络公司); 新兴公司,新开张的企业; specific具体的,特定的:factual 事实的, ...