POJ 1236

给定一个有向图,求:

1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点

2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点

第一个就是缩点之后有多少入度为0的个数因为一定要从这些节点出发

第二个就是因为图本身就是联通的,设入度为0的点有n个,出度为0的点有m个,

那么入度的编号为N0,N1,N2,N3...Nn,出度编号为M0,M1,M2...Mm 

那么连N0->M0->N1->M1->N2->M3。这样形成环啦那连到Min(n,m)时就会结束了剩下的Abs(n-m)点,连起来就有Max(n,m)个点啦.

 #include <cstring>
const int Maxn=;
const int Maxm=;
struct EDGE{int to,next;}edge[Maxm<<];
int head[Maxn],Dfn[Maxn],Low[Maxn],Belong[Maxn],In[Maxn],Out[Maxn],Stack[Maxn],Top,vis[Maxn],n,cnt,Stamp,Scc,x;
inline int Max(int x,int y) {return x>y?x:y;}
inline int Min(int x,int y) {return x>y?y:x;}
inline void Add(int u,int v) {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;} void Tarjan(int u,int fa)
{
Low[u]=Dfn[u]=++Stamp; Stack[++Top]=u; vis[u]=true;
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (v==fa) continue;
if (!Dfn[v])
{
Tarjan(v,u);
Low[u]=Min(Low[u],Low[v]);
} else if (vis[v]) Low[u]=Min(Low[u],Dfn[v]);
}
if (Dfn[u]==Low[u])
{
Scc++; int v=;
while (v!=u)
{
v=Stack[Top--];
vis[v]=false;
Belong[v]=Scc;
}
}
}
int main()
{
// freopen("c.in","r",stdin);
scanf("%d",&n);
memset(head,-,sizeof(head));
for (int i=;i<=n;i++)
while (scanf("%d",&x)&&x)
Add(i,x);
memset(vis,false,sizeof(vis)); Scc=;
for (int i=;i<=n;i++) if (!Dfn[i]) Tarjan(i,);
for (int u=;u<=n;u++)
for (int i=head[u];i!=-;i=edge[i].next)
if (Belong[u]!=Belong[edge[i].to]) In[Belong[edge[i].to]]++,Out[Belong[u]]++;
int Tmp1=,Tmp2=;
for (int i=;i<=Scc;i++)
{
if (In[i]==) Tmp1++;
if (Out[i]==) Tmp2++;
}
if (Scc==)
{
puts("");
puts("");
return ;
}
printf("%d\n",Tmp1);
printf("%d\n",Max(Tmp1,Tmp2));
return ;
}

POJ 1236

POJ 3177

给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图。

Tarjan缩点后统计叶子节点的个数,给两个相连就可以了 所以Sum=(Ans+1)>>1;

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int Maxn=;
const int Maxm=;
struct EDGE{int to,next;}edge[Maxm<<];
int head[Maxn],Dfn[Maxn],Low[Maxn],vis[Maxn],n,m,u,v,cnt,Top,Stack[Maxn],d[Maxn],Scc,Stamp,Belong[Maxn],Ans;
inline void Add(int u,int v) {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
inline int Min(int x,int y) {return x>y?y:x;} void Tarjan(int u,int fa)
{
Dfn[u]=Low[u]=++Stamp; Stack[++Top]=u; vis[u]=true;
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (i==(fa^)) continue;
if (!Dfn[v])
{
Tarjan(v,i);
Low[u]=Min(Low[u],Low[v]);
} else if (vis[v]) Low[u]=Min(Low[u],Dfn[v]);
}
if (Dfn[u]==Low[u])
{
Scc++;
while (true)
{
int v=Stack[Top--];
vis[v]=false;
Belong[v]=Scc;
if (v==u) break;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(head,-,sizeof(head));
for (int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
Add(u,v),Add(v,u);
}
for (int i=;i<=n;i++) if (!Dfn[i]) Tarjan(i,-);
for (int u=;u<=n;u++)
{
for (int i=head[u];i!=-;i=edge[i].next)
if (Belong[u]!=Belong[edge[i].to]) d[Belong[u]]++;
}
for (int i=;i<=Scc;i++) if (d[i]==) Ans++;
printf("%d\n",(Ans+)>>);
return ;
}

POJ 3177

POJ 1144

给你一个图,求有多少个割点

u为树根,且u有多于一个子树。 (2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int Maxn=;
const int Maxm=;
struct EDGE{int to,next;}edge[Maxm];
int head[Maxn],Dfn[Maxn],Low[Maxn],Root,Son,u,v,n,cnt,Stamp;
bool Cut[Maxn];
inline int Min(int x,int y) {return x>y?y:x;}
inline void Add(int u,int v) {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
void Tarjan(int u)
{
Dfn[u]=Low[u]=++Stamp;
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (!Dfn[v])
{
Tarjan(v);
if (u==Root) Son++;
else
{
Low[u]=Min(Low[u],Low[v]);
if (Dfn[u]<=Low[v]) Cut[u]=true;
}
} else
Low[u]=Min(Low[u],Dfn[v]);
}
}
int main()
{
while (scanf("%d",&n)!=EOF && n!=)
{
memset(head,-,sizeof(head));
memset(Dfn,,sizeof(Dfn));
memset(Low,,sizeof(Low));
memset(Cut,false,sizeof(Cut)); Stamp=; cnt=;
while (scanf("%d",&u)!=EOF && u!=)
while (getchar()!='\n')
{
scanf("%d",&v);
Add(u,v),Add(v,u);
}
Root=,Son=;
Tarjan();
int Ans=;
if (Son>) Ans=;
for (int i=;i<=n;i++) if (Cut[i]) Ans++;
printf("%d\n",Ans);
}
return ;
}

POJ 1144

POJ 2186

求出度为0的奶牛的个数即可

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int Maxn=;
const int Maxm=;
struct EDGE{int to,next;}edge[Maxm<<];
int n,m,Dfn[Maxn],Low[Maxn],head[Maxn],Stack[Maxn],Belong[Maxn],Scc,Stamp,cnt,Top,u,v,Out[Maxn],vis[Maxn],Size[Maxn];
inline void Add(int u,int v) {edge[cnt].to=v;edge[cnt].next=head[u]; head[u]=cnt++;}
inline int Min(int x,int y) {return x>y?y:x;}
void Tarjan(int u)
{
Dfn[u]=Low[u]=++Stamp; Stack[++Top]=u; vis[u]=true;
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (!Dfn[v])
{
Tarjan(v);
Low[u]=Min(Low[u],Low[v]);
} else
if (vis[v])
Low[u]=Min(Low[u],Dfn[v]);
}
if (Dfn[u]==Low[u])
{
Scc++;
int v=;
while (v!=u)
{
v=Stack[Top--];
Belong[v]=Scc,++Size[Scc];
vis[v]=false;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(head,-,sizeof(head));
for (int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
Add(u,v);
}
for (int i=;i<=n;i++)
if (!Dfn[i]) Tarjan(i);
for (int u=;u<=n;u++)
{
for (int i=head[u];i!=-;i=edge[i].next)
if (Belong[u]!=Belong[edge[i].to]) Out[Belong[u]]++;
}
int Zero=,k=;
for (int i=;i<=Scc;i++)
if (!Out[i])
{
Zero++;
k=Size[i];
}
Zero>?puts(""):printf("%d\n",k);
return ;
}

POJ2186

POJ 3352

一个连通的无向图,求至少需要添加几条边,救能保证删除任意一条边,图仍然是连通的,即成为双连通分量

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int Maxn=;
const int Maxm=;
struct EDGE{int to,next;}edge[Maxm<<];
int head[Maxn],Dfn[Maxn],Low[Maxn],vis[Maxn],n,m,u,v,cnt,Top,Stack[Maxn],d[Maxn],Scc,Stamp,Belong[Maxn],Ans;
inline void Add(int u,int v) {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
inline int Min(int x,int y) {return x>y?y:x;}
void Tarjan(int u,int fa)
{
Dfn[u]=Low[u]=++Stamp; Stack[++Top]=u; vis[u]=true;
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (v==fa) continue;
if (!Dfn[v] && !vis[v])
{
Tarjan(v,u);
Low[u]=Min(Low[u],Low[v]);
} else if (vis[v]) Low[u]=Min(Low[u],Dfn[v]);
}
if (Dfn[u]==Low[u])
{
Scc++;
while (Stack[Top]!=u && Top>=) Belong[Stack[Top--]]=Scc;
Belong[Stack[Top--]]=Scc;
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(head,-,sizeof(head));
for (int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
Add(u,v),Add(v,u);
}
Tarjan(,);
for (int u=;u<=n;u++)
{
for (int i=head[u];i!=-;i=edge[i].next)
if (Belong[u]!=Belong[edge[i].to]) d[Belong[edge[i].to]]++;
} for (int i=;i<=Scc;i++) if (d[i]==) Ans++;
printf("%d\n",(Ans+)>>);
return ;
}

POJ 3352

HDU 3394

一个无向图(可能不连通)有n个点和m条边.现在要你找出冲突边和多余边的数目.其中冲突边是那些同时存在于多个环中的边,而多余边是不在任何一个环中的边.当点数=边数,形成一个环,当点数>边数(一条线段,说明这条边是桥),当点数<边数,那么就含1个以上的环了

 #include <cstdio>
#include <cstring>
const int Maxn=;
const int Maxm=;
const int Inf=0x3f3f3f3f;
int Low[Maxn],Dfn[Maxn],Bcc[Maxn],vis[Maxn],Stamp,Top,cnt,u,v,Bridge,Way;
int head[Maxn],Stack[Maxn],n,m,belong[Maxn];
struct EDGE{int to,next;}edge[Maxm<<];
inline int Min(int x,int y) {return x>y?y:x;}
inline void Add(int u,int v)
{edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
inline void CirCuit()
{
int Cnt=;
memset(belong,false,sizeof(belong));
for (int i=;i<=Bcc[];i++) belong[Bcc[i]]=true;
for (int j=;j<=Bcc[];j++)
{
int u=Bcc[j];
for (int i=head[u];i!=-;i=edge[i].next)
if (belong[edge[i].to]) Cnt++;
}
Cnt>>=;
if (Cnt>Bcc[]) Way+=Cnt;
}
void Tarjan(int u,int fa)
{
Low[u]=Dfn[u]=++Stamp; Stack[++Top]=u; vis[u]=true;
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (fa==(i^)) continue;
if (!Dfn[v])
{
Tarjan(v,i);
Low[u]=Min(Low[u],Low[v]);
if (Low[v]>=Dfn[u])
{
if (Low[v]>Dfn[u]) Bridge++;
Bcc[]=;
while (true)
{
int x=Stack[Top--];
Bcc[++Bcc[]]=x;
if (x==v) break;
}
Bcc[++Bcc[]]=u;
CirCuit();
}
} else if (vis[v]) Low[u]=Min(Low[u],Dfn[v]);
}
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n== && m==) break;
cnt=; memset(head,-,sizeof(head));
memset(Dfn,,sizeof(Dfn)); Top=;
memset(Low,,sizeof(Low)); Stamp=;
memset(vis,false,sizeof(vis));
Bridge=Way=;
for (int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
Add(u,v),Add(v,u);
}
for (int i=;i<=n;i++) if (!Dfn[i]) Tarjan(i,-);
printf("%d %d\n",Bridge,Way);
}
return ;
}

HDU 3394

NOIP 考前 Tarjan复习的更多相关文章

  1. noip考前模板复习

    网络流 Dinic(搭配飞行员) //Serene #include<algorithm> #include<iostream> #include<cstring> ...

  2. NOIP 考前 队列复习

    BZOJ 1127 #include <cstdio> #include <cstring> #include <iostream> #include <al ...

  3. NOIP 考前 数论复习

    POJ 2891 x=r1 (mod a1) x=r2 (mod a2) x=a1*x+r1,x=a2*y+r2; a1*x-a2*y=r2-r1; 用Extend_Gcd求出m1*x+m2*y=d; ...

  4. NOIP 考前 数据结构复习

    BZOJ 1455 左偏树即可 #include <cstdio> #define LL long long ; struct Info{LL l,r,v,Dis;}Tree[Maxn]; ...

  5. NOIP 考前DP 复习

    POJ 2533 最长不降子序列 #include <cstdio> ; int a[Maxn],Pos[Maxn],F[Maxn],n,Ans; inline int Max(int x ...

  6. NOIP考前划水

    NOIP考前划水 君指先跃动の光は.私の一生不変の信仰に.唯私の超電磁砲永世生き! 要开始背配置了? 3行不谢. (setq c-default-style "awk") (glo ...

  7. Noip前的大抱佛脚----Noip真题复习

    Noip前的大抱佛脚----Noip真题复习 Tags: Noip前的大抱佛脚 Noip2010 题目不难,但是三个半小时的话要写四道题还是需要码力,不过按照现在的实力应该不出意外可以AK的. 机器翻 ...

  8. tarjan复习笔记

    tarjan复习笔记 (关于tarjan读法,优雅一点读塔洋,接地气一点读塔尖) 0. 连通分量 有向图: 强连通分量(SCC)是个啥 就是一张图里面两个点能互相达到,那么这两个点在同一个强连通分量里 ...

  9. NOIP 考前 并查集复习

    POJ 1182 把一个点拆成x,x+n,x+2*n,x吃y可以表示认为x,y+n是一类的,x+n,y+2*n是一类,x+2*n,y是一类. #include <cstdio> ; ],n ...

随机推荐

  1. 基于jstree的 对混乱的 命名系统进行归类的 计算机软件

    本人现在就职于一家加拿大东部餐饮连锁公司的IT部门,公司旗下有4个品牌,280多家餐厅. 所有的餐厅都使用maitred 的pos软件来处理收银结账. 公司总部使用business object 对m ...

  2. C# Socket连接 无法访问已释放的对象

    在进行Socket长连接时,若服务器或客户端出现异常时,另外一端对Socket对话进行操作时,程序会出现无法访问已释放的对象的问题.例如客户端出现问题主动断开Socket时,当服务器操作Socket时 ...

  3. SAP SE11 网格布局显示

    SE11 进入数据显示界面后 在  Settings -> User Parameters,  Data Browser 页面 勾选ALV Grid display 即可.

  4. 安装Windows 10后PDF补丁丁等程序界面变得模糊的解决办法

    对于使用高分辨率屏幕且屏幕缩放比例在 100%以上的用户,升级到 Windows 10 后将发现许多程序的界面,例如QQ.电脑管家.Windows本身的服务管理程序等等,都变得非常模糊,<PDF ...

  5. WPF中Grid布局

    WPF中Grid布局XMAl与后台更改,最普通的登录界面为例. <Grid Width="200" Height="100" > <!--定义 ...

  6. 数据加密标准——DES

    DES算法和DESede算法统称DES系列算法.DES算法是对称加密算法领域中的典型算法,为后续对称加密算法的发展奠定了坚实的基础.但是DES算法密钥偏短,仅有56位,迭代次数偏少,受到诸如查分密码分 ...

  7. 通过npm安装 Cordova

    通过npm安装 Cordova 首先请确保你在本地已经安装了NodeJS(可以调用npm命令), 并且是联网状态的.如果不知道如何安装NodeJS, 请参考 ”四步完成NodeJS安装,配置和测试”. ...

  8. WCF传输大数据的设置2

    本节主要内容:1.如何读取Binding中的binding元素.2.CustomBinding元素的基本配置.3.代码示例 一.Bingding是由binding元素构成的,可以根据实际需要,进行适当 ...

  9. 2014中国黑客榜(beta版)

    黑客,英文hacker.精通计算机各类技术的计算机高手,泛指擅长IT技术的人群.计算机科学家. 最近受某机构所托搜集国内活跃黑客近况.本着客观专业,权威可信的原则参考了国内从00年到最新的黑客榜单,以 ...

  10. ubuntu 下安装mysql,以及配置远程登录

    安装MysQL 在Ubuntu14.04下安装MySQL比较简单,只需下面这条命令就行了: 1.输入 sudo apt-get install mysql-server 2.继续执行后,需要设定MyS ...