在图中求双联通和强联通分量是我们解决非树结构的图连通问题的利器

通过求求图的双联通和强联通分量能把图转化成DAG进行求解;

行走

Description

给出一个有向图,你可以选择从任意点出发走到任意点结束,问最多可以经过多少个点(重复经过只算一次)。

Input Format

第一行,两个整数,n和m。表示有向图的点数和边数。

接下来是m行每行输入两个数a,b,表示有一条从a到b的路。

Output Format

输出最多可以经过的点数

Sample Input

10 10
6 4
0 8
5 9
8 1
7 7
4 8
5 9
7 5
9 5
7 7

Sample Output

4

Hint

对于30%的数据,1≤n,m≤10

对于100%的数据,1≤n,m≤10000,0≤a,b

题目不保证图是拓扑结构(DAG)那么就有可能出现自环枚举每个点搜图效率慢T(n(m+n));

暴力算法明显超时 这时求强联通分量进行缩点就派上用场;

若把图转成DAG那么就可以通过每颗树的根节点搜索图 进行统计了T(n+m)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#define maxn 100010
using namespace std;
int n,m,i,j,k,top,tim,t,co,ans;
struct st{int nex,to;}mu[2*maxn];
int s[maxn],pre[maxn],low[maxn],last[maxn],bcc[maxn],xx[maxn],yy[maxn],sum[maxn],bo[maxn];
int dfs(int u)
{
int v;
s[++top]=u;
low[u]=pre[u]=++tim;
for(int z=last[u];z;z=mu[z].nex)
{
v=mu[z].to;
if(!pre[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!bo[v])
low[u]=min(low[u],pre[v]);
}
if(low[u]==pre[u])
{
++co;
int num=0;
for(; ;)
{
num++;
bo[s[top]]=co;
bcc[s[top--]]=co;
if(s[top+1]==u)break;
}
sum[co]=num;
}
return low[u];
}
void dfs1(int u)
{
low[u]=sum[u];
int p=0;
for(int z=last[u];z;z=mu[z].nex)
{
if(!low[mu[z].to])
dfs1(mu[z].to);
p=max(p,low[mu[z].to]);
}
low[u]+=p;
}
int main()
{
// freopen("xx.in","r",stdin);
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i)
{
int u,v;
scanf("%d%d",&xx[i],&yy[i]);
t++;mu[t].nex=last[xx[i]];
mu[t].to=yy[i];last[xx[i]]=t;
}
for(i=0;i<n;++i)
if(!pre[i])
{
tim=0;top=0;dfs(i);
}
for(i=0;i<=co;++i)
low[i]=s[i]=last[i]=0;t=0;
for(i=1;i<=m;++i)
{
int u=bcc[xx[i]],v=bcc[yy[i]];
if(u==v)continue;
t++;mu[t].nex=last[u];
mu[t].to=v;last[u]=t;s[v]++;
}
for(i=1;i<=co;++i)
if(!s[i])
{
dfs1(i);
ans=max(ans,low[i]);
}
printf("%d",ans);
}

间谍网络

Description

由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。

我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。

请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。

Input Format

输入文件age.in第一行只有一个整数n。

第二行是整数p。表示愿意被收买的人数,1≤p≤n。

接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000。

紧跟着一行只有一个整数r,1≤r≤8000。然后r行,每行两个正整数,表示数对(A, B),A间谍掌握B间谍的证据。

Output Format

如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。

Sample Input

【样例1】
age.in
3
2
1 10
2 100
2
1 3
2 3 【样例2】
age.in
4
2
1 100
4 200
2
1 2
3 4

Sample Output

【样例1】
YES
110 【样例2】
NO
3
如果间谍网出现强联通分量那么只要其中一个能被收买就能逮捕强联通分量内的所有间谍(只收买最便宜的间谍);
那么就求强联通进行缩点 ;然后只要收买树根的间谍就行了;
为什么? 因为你要收买所有间谍 树根的间谍一定要收买 那么一整棵树的间谍都被逮捕了;
只要每颗树的树根都能收买 那么一定能控制所有间谍;
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#define maxn 3010
using namespace std;
int n,i,j,k,l,m,p,co,tim,top,t,ans;
struct st{int nex,to;}mu[maxn*6];
int s[maxn],last[maxn],bcc[maxn],bo[maxn],pre[maxn],low[maxn],b[maxn],xx[maxn*3],yy[maxn*3];
int dfs(int u)
{
pre[u]=low[u]=++tim;
int v;s[++top]=u;
for(int z=last[u];z;z=mu[z].nex)
{
v=mu[z].to;
if(!pre[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!b[maxn])
low[u]=min(low[u],pre[v]);
}
if(pre[u]==low[u])
{
++co;
for(; ;)
{
b[s[top]]=1;
bcc[s[top--]]=co;
if(s[top+1]==u)break;
}
}
}
void add(int x,int y)
{
t++;mu[t].nex=last[x];
mu[t].to=y;last[x]=t;
}
int main()
{
// freopen("xx.in","r",stdin);
scanf("%d%d",&n,&p);
for(i=1;i<=p;++i)
{
int u,v;
scanf("%d%d",&u,&v);
bo[u]=v+1;
}
scanf("%d",&m);
for(i=1;i<=m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
xx[i]=u;yy[i]=v;
}
for(i=1;i<=n;++i)
if(!pre[i])
{
top=tim=0;
dfs(i);
}
for(i=1;i<=co;low[i]=1e9,++i)s[i]=b[i]=0;
for(i=1;i<=m;++i)
{
if(bcc[xx[i]]==bcc[yy[i]])continue;
s[bcc[yy[i]]]=1;
}
for(i=1;i<=n;++i)
if(bo[i])
low[bcc[i]]=min(low[bcc[i]],bo[i]-1);
for(i=1;i<=co;++i)
if(!s[i])
{
if(low[i]==1e9)
{
for(j=1;j<=n;++j)
if(bcc[j]==i)break;
printf("NO\n%d",j);
return 0;
}
ans+=low[i];
}
printf("YES\n%d",ans);
}

 

Freda的迷宫

Description

Freda是一个迷宫爱好者,她利用业余时间建造了许多迷宫。每个迷宫都是由若干房间和走廊构成的,每条走廊都连接着两个不同的房间,两个房间之间最多只有一条走廊直接相连,走廊都是双向通过。

黄昏时候,Freda喜欢在迷宫当中漫步。每天,Resodo都会为Freda设计一个挑战方案。Resodo会指定起点和终点,请Freda来找到一条从起点到终点的简单路径。一条简单路径定义为一个房间序列,每个房间至多在序列里出现一次,且序列中相邻的两个房间有走廊相连。当起点和终点之间存在且仅存在一条简单路径的时候,Freda认为这个挑战方案是RD的。现在,请你帮帮Resodo来写一个程序,判断一个挑战方案是否是RD的。

Input Format

第一行三个整数N,M,Q.分别表示房间数,走廊数,询问数。

接下来M行每行2个整数x,y, 0<=N, 表示x和y之间有一条走廊相连。

接下来Q行每行2个整数x,y, 表示询问以x为起点,y为终点的挑战方案是否是RD的.

Output Format

对于每个询问,输出一行”Y”或者”N”(不含引号).Y表示该询问所表示的挑战方案是RD的,N表示该询问所表示的挑战方案不是RD的.

Sample Input

6 5 3
1 2
2 3
2 4
2 5
4 5
1 3
1 5
2 6

Sample Output

Y
N
N

Hint

样例解释

1,3之间只有一条路径 1->2->3

1,5之间有两条路径 1->2->5 ; 1->2->4->5

1,6之间没有路径

数据范围与约定

对于30%的数据,N<=100, M<=1000, Q<=100.

对于50%的数据,N<=1000, M<=10000, Q<=1000.

对于100%的数据,N<=10000, M<=100000, Q<=10000.

按题意在线处理定会超时;

怎么做到离线算法?

首先有简单路径必须保证两点联通 且只有唯一路径;

那么这条路径一定由桥组成;那就可以保证路径唯一,且联通;

用Tarjan求桥;

将桥两端点归进一个集合 这时就要用到并查集了;

最后对于每个询问只要判断两点在同一集合就能保证有唯一路径;

#include<cstdio>
#include<iostream>
#define maxn 10010
using namespace std;
int n,t,i,j,k,l,m,q,tim,_bcc,_scc,top,fu,fv;
int last[maxn],bcc[maxn],scc[maxn],pre[maxn],low[maxn],f[maxn];
struct st{int nex,to;}mu[maxn*20];
void add(int x,int y)
{
t++;mu[t].nex=last[x];
mu[t].to=y;last[x]=t;
}
int gets(int x)
{return f[x]==x ? x:f[x]=gets(f[x]);}
int dfs(int u,int fa)
{
pre[u]=low[u]=++tim;
int v;
for(int z=last[u];z;z=mu[z].nex)
{
v=mu[z].to;
if(!pre[v])
{
dfs(v,u);
low[u]=min(low[u],low[v]);
if(pre[u]<low[v])
{
fu=gets(u);fv=gets(v);
if(fu!=fv)f[fv]=fu;
}
}
else if(pre[u]>pre[v]&v!=fa)
low[u]=min(pre[v],low[u]);
}
return low[u];
}
int main()
{
// freopen("xx.in","r",stdin);
scanf("%d%d%d",&n,&m,&q);
for(i=1;i<=m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
for(i=1;i<=n;++i)f[i]=i;
for(i=1;i<=n;++i)
if(!pre[i])
{
tim=0;top=0;
dfs(i,-1);
}
for(i=1;i<=q;++i)
{
int u,v;
scanf("%d%d",&u,&v);
u=gets(u);v=gets(v);
if(u==v)printf("Y\n");
else printf("N\n");
}
}

  

Tarjan 求图点强联通,桥的应用的更多相关文章

  1. POJ 1236--Network of Schools【scc缩点构图 &amp;&amp; 求scc入度为0的个数 &amp;&amp; 求最少加几条边使图变成强联通】

    Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13325   Accepted: 53 ...

  2. Tarjan求割点(割顶) 割边(桥)

    割点的定义: 感性理解,所谓割点就是在无向连通图中去掉这个点和所有和这个点有关的边之后,原先连通的块就会相互分离变成至少两个分离的连通块的点. 举个例子: 图中的4号点就是割点,因为去掉4号点和有关边 ...

  3. HDU 4635 多校第四场 1004 强联通

    我还有什么好说,还有什么好说...... 我是SBSBSBSBSBSBSBSBSBSBSBSBBSBSBSBSBSBSBSBSBS........................ 题意 思路什么的都不 ...

  4. POJ 2186 Popular Cows(强联通分量)

    题目链接:http://poj.org/problem?id=2186 题目大意:    每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种 ...

  5. POJ 2762Going from u to v or from v to u?(强联通 + 缩点 + 拓扑排序)

    [题意]: 有N个房间,M条有向边,问能否毫无顾虑的随机选两个点x, y,使从①x到达y,或者,②从y到达x,一定至少有一条成立.注意是或者,不是且. [思路]: 先考虑,x->y或者y-> ...

  6. 【强联通分量缩点】【最长路】【spfa】CH Round #59 - OrzCC杯NOIP模拟赛day1 队爷的讲学计划

    10分算法:对于城市网络为一条单向链的数据, 20分算法:对于n<=20的数据,暴力搜出所有的可能路径. 结合以上可以得到30分. 60分算法:分析题意可得使者会带着去的城市也就是这个城市所在强 ...

  7. 校园网络 luogu P2812 (又是强联通)

    题目传送门!(luogu) 首先考虑问题一 不难想到,如果有一个学校作为终端机,那么跟其处于同一个强联通中的所有学校就可以不用作为终端机了. 那么,问题一也就迎刃而解了:找到所有入度为0的缩点.因为这 ...

  8. HDU 2767 Proving Equivalences (强联通)

    pid=2767">http://acm.hdu.edu.cn/showproblem.php?pid=2767 Proving Equivalences Time Limit: 40 ...

  9. Tarjan求强联通分量+缩点

    提到Tarjan算法就不得不提一提Tarjan这位老人家 Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名.他拥有丰富的商业工作经验,1985年开始任教于普林斯顿大学.Tarj ...

随机推荐

  1. PHP在Linux的Apache环境下乱码解决方法

    在windows平台编写的php程序默认编码是gb2312 而linux和apche默认的编码都是UTF-8 所以windows平台编写的php程序传到linux后,浏览网页中文都是乱码. 如果手工将 ...

  2. VFS(Virtual File System)

    一.VFS作为内核子系统,为用户空间程序提供了文件系统相关的接口.所有实际文件系统依赖VFS共存,依靠VFS系统工作. 1.VFS提供通用文件系统接口:用户空间程序可以利用标准的UNIX文件系统调用, ...

  3. HTML5 Canvas绘制的下雪效果

    在HTML页面的HEAD区域直接引入snow.js即可,如下:<script type="text/javascript" src="js/snow.js" ...

  4. Vue学习之路第十一篇:为页面元素设置class类样式

    1.class为页面元素的一个属性,通过前面第五篇的内容可知,操作属性需要使用到v-bind指定(也可简写为 :). 2.先来看一个简单的页面样式内容: <!DOCTYPE html> & ...

  5. POJ 1258 Agri-Net( 裸最小生成树 )

    链接:传送门! 题意:一个裸最小生成树,采用Kruskal. /******************************************************************** ...

  6. HDU 5307 He is Flying (生成函数+FFT)

    题目传送门 题目大意:给你一个长度为$n$的自然数序列$a$,定义一段区间的权值为这一段区间里所有数的和,分别输出权值为$[0,\sum a_{i}]$的区间的长度之和 想到了生成函数的话,这道题并不 ...

  7. [luogu 1270] “访问”美术馆 (树形dp)

    传送门 Description 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室.Peer知道每 ...

  8. 【hdu 6438】Buy and Resell

    [链接] 我是链接,点我呀:) [题意] 有一个物品的价格在1..n这些位置各不相同. 你初始有无限的钱. 问你从1走到n. 你每次可以选择买入一个或者卖出一个该种物品(或啥都不做) 问你最后的最大利 ...

  9. Activiti 各个节点涉及的表

    ################################# 部署流程定义涉及到的表 # 流程部署表SELECT * FROM `act_re_deployment` # 流程定义表SELECT ...

  10. (转)关于使用iText导出pdf

    一.iText简介 iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文 ...