Tarjan 求图点强联通,桥的应用
在图中求双联通和强联通分量是我们解决非树结构的图连通问题的利器
通过求求图的双联通和强联通分量能把图转化成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 求图点强联通,桥的应用的更多相关文章
- POJ 1236--Network of Schools【scc缩点构图 && 求scc入度为0的个数 && 求最少加几条边使图变成强联通】
Network of Schools Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 13325 Accepted: 53 ...
- Tarjan求割点(割顶) 割边(桥)
割点的定义: 感性理解,所谓割点就是在无向连通图中去掉这个点和所有和这个点有关的边之后,原先连通的块就会相互分离变成至少两个分离的连通块的点. 举个例子: 图中的4号点就是割点,因为去掉4号点和有关边 ...
- HDU 4635 多校第四场 1004 强联通
我还有什么好说,还有什么好说...... 我是SBSBSBSBSBSBSBSBSBSBSBSBBSBSBSBSBSBSBSBSBS........................ 题意 思路什么的都不 ...
- POJ 2186 Popular Cows(强联通分量)
题目链接:http://poj.org/problem?id=2186 题目大意: 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种 ...
- POJ 2762Going from u to v or from v to u?(强联通 + 缩点 + 拓扑排序)
[题意]: 有N个房间,M条有向边,问能否毫无顾虑的随机选两个点x, y,使从①x到达y,或者,②从y到达x,一定至少有一条成立.注意是或者,不是且. [思路]: 先考虑,x->y或者y-> ...
- 【强联通分量缩点】【最长路】【spfa】CH Round #59 - OrzCC杯NOIP模拟赛day1 队爷的讲学计划
10分算法:对于城市网络为一条单向链的数据, 20分算法:对于n<=20的数据,暴力搜出所有的可能路径. 结合以上可以得到30分. 60分算法:分析题意可得使者会带着去的城市也就是这个城市所在强 ...
- 校园网络 luogu P2812 (又是强联通)
题目传送门!(luogu) 首先考虑问题一 不难想到,如果有一个学校作为终端机,那么跟其处于同一个强联通中的所有学校就可以不用作为终端机了. 那么,问题一也就迎刃而解了:找到所有入度为0的缩点.因为这 ...
- HDU 2767 Proving Equivalences (强联通)
pid=2767">http://acm.hdu.edu.cn/showproblem.php?pid=2767 Proving Equivalences Time Limit: 40 ...
- Tarjan求强联通分量+缩点
提到Tarjan算法就不得不提一提Tarjan这位老人家 Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名.他拥有丰富的商业工作经验,1985年开始任教于普林斯顿大学.Tarj ...
随机推荐
- C# DataTable 转 json
public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //窗体 ...
- BZOJ 3456: 城市规划 多项式求逆
Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接 ...
- bzoj 1296: [SCOI2009]粉刷匠 动态规划
Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个 ...
- Node-Blog整套前后端学习记录
Node-Blog 后端使用node写的一个一整套的博客系统 #### 主要功能 登录 注册 发表文章 编辑/删除文章 添加/删除/编辑文章分类 账号的管理 评论功能 ... 所用技术 node ex ...
- FreeMarker hello
一.什么是 FreeMarker FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 ...
- Python docs
刚刚发现了Python好用的文档查询网页:Python docs,可以选择python版本查询,跟OpenCV docs很相似,很好用-
- 如何打开WCF测试客户端
- nodejs-EventEmitter
addListener(event, listener)为指定事件添加一个监听器到监听器数组的尾部. on(event, listener)为指定事件注册一个监听器,接受一个字符串 event 和一个 ...
- 洛谷—— P1120 小木棍 [数据加强版]
https://www.luogu.org/problem/show?pid=1120 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接 ...
- centos: git clone提示Permission denied publickey 问题
问题: Initialized empty Git repository in /data1/mouxuan/fastsocket-private/.git/ Permission denied (p ...