桥
low[v]>dfn[u] //成立条件
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e6+10;
ll n,m,cnt=0,ct=0,ti=0;
ll fa[maxn],head[maxn],dfn[maxn],low[maxn];
struct edge{
ll u,v,nex;
}e[maxn],ans[maxn];
ll cmp(edge x,edge y){
if(x.u!=y.u) return x.u<y.u;
return x.v<y.v;
}
void add(ll u,ll v){
cnt++;
e[cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
}
void addedge(ll u,ll v){
if(u>v){
ll t=u;
u=v;
v=t;
}
ct++;
ans[ct].u=u;
ans[ct].v=v;
}
void tarjan(ll u){
dfn[u]=low[u]=++ti;
for(ll i=head[u];i;i=e[i].nex){
ll v=e[i].v;
if(dfn[v]&&fa[u]!=v) low[u]=min(low[u],dfn[v]);
if(!dfn[v]){
fa[v]=u;
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) addedge(u,v);
}
}
}
int main()
{
cin>>n>>m;
for(ll i=1;i<=m;i++){
ll u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
tarjan(1);
sort(ans+1,ans+1+ct,cmp);
for(ll i=1;i<=ct;i++){
cout<<ans[i].u<<' '<<ans[i].v<<endl;
}
return 0;
}
割点
low[v]>=dfn[u] //子节点条件
isroot==u&&tot>=2 //是根节点且子节点个数大于等于2
isroot!=u&&tot>=1 //不是根节点且子节点个数大于等于1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e5+10;
ll head[maxn],dfn[maxn],low[maxn],ans[maxn];
ll n,m,isroot,cnt=0,idx=0;
ll ti=0;
struct edge{
ll v,nex;
}e[maxn<<1];
void add(ll u,ll v){
cnt++;
e[cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
}
void tarjan(ll u){
ll tot=0;
dfn[u]=low[u]=++ti;
for(ll i=head[u];i;i=e[i].nex){
ll v=e[i].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]) tot++;
}else {
low[u]=min(low[u],dfn[v]);
}
}
if( (isroot==u&&tot>=2)||(isroot!=u&&tot>=1) ){
idx++;
ans[idx]=u;
}
}
int main()
{
cin>>n>>m;
for(ll i=1;i<=m;i++){
ll u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
// tarjan(1);
for(ll i=1;i<=n;i++){
if(dfn[i]==0) {
isroot=i;
tarjan(i);
}
}
sort(ans+1,ans+1+idx);
cout<<idx<<endl;
for(ll i=1;i<=idx;i++){
cout<<ans[i];
if(i!=idx) cout<<' ';
else cout<<endl;
}
return 0;
}
缩点
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e5+10;
ll n,m;
ll dfn[maxn],low[maxn];
ll w[maxn],ww[maxn];
ll head[maxn],hd[maxn];
ll rep[maxn];
ll cnt=0,cntt=0;
ll tim=0;
ll rudu[maxn];
ll ans=0;
ll dist[maxn];
ll vis[maxn];
struct edge{
ll v,nex,u;
}e[maxn],ed[maxn];
void add(ll u,ll v){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
return ;
}
void init(){
memset(head,0,sizeof(head));
memset(hd,0,sizeof(hd));
memset(vis,0,sizeof(vis));
return ;
}
stack<ll>st;
void tarjan(ll u){
low[u]=dfn[u]=++tim;//时间戳 首次访问时间
vis[u]=1;
st.push(u);
for(ll i=head[u];i;i=e[i].nex){
ll v=e[i].v;
if(dfn[v]==0){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(vis[v]==1){
low[u]=min(low[u],dfn[v]);
}
}
// cout<<"YES"<<endl;
if(dfn[u]==low[u]){//出栈
while(st.empty()!=1){
ll t =st.top();
st.pop();
rep[t]=u;
if(u!=t)
w[u]+=w[t];
vis[t]=0;
if(u==t){
break;
}
}
}
return ;
}
queue<ll>q;
void toposort(){
for(ll i=1;i<=n;i++){
if(rep[i]==i&&rudu[i]==0){
q.push(i);
dist[i]=w[i];
}
}
while(q.empty()!=1){
ll u=q.front();
q.pop();
for(ll i=hd[u];i;i=ed[i].nex){
ll v=ed[i].v;
dist[v]=max(dist[v],dist[u]+w[v]);
rudu[v]--;
if(rudu[v]==0) q.push(v);
}
}
for(ll i=1;i<=n;i++){
if(rep[i]==i){
ans=max(ans,dist[i]);
}
}
return ;
}
void show(){
for(ll i=1;i<=n;i++){
cout<<w[i]<<' ';
}
cout<<endl;
for(ll i=1;i<=n;i++){
cout<<rep[i]<<' ';
}
cout<<endl;
}
int main()
{
init();
cin>>n>>m;
for(ll i=1;i<=n;i++){
cin>>w[i];
}
ll u,v;
for(ll i=1;i<=m;i++){
cin>>u>>v;
add(u,v);
}
for(ll i=1;i<=n;i++){
if(dfn[i]==0) tarjan(i);
}
for(ll i=1;i<=m;i++){
ll x=rep[e[i].u];
ll y=rep[e[i].v];
if(x!=y){
cntt++;
ed[cntt].v=y;
ed[cntt].u=x;
ed[cntt].nex=hd[x];
hd[x]=cntt;
rudu[y]++;
}
}
// show();
toposort();
cout<<ans<<endl;
return 0;
}