一、先上模板QWQ
#include<bits/stdc++.h>//tarjan-强连通分量
using namespace std;
const int MAXM=100005;
const int MAXN=5005;
int n,m,tot,head[MAXN],dfn[MAXN],low[MAXN],cntt;
int colour[MAXN],cnt[MAXN],maxcnt,cntcol,sta[MAXN][MAXN];
bool vis[MAXN];
struct sth{
int to,nxt;
}a[MAXM];
void add(int u,int v,int w){
a[++tot].to=v;a[tot].nxt=head[u];
head[u]=tot;
if(w==2){a[++tot].to=u;
a[tot].nxt=head[v];head[v]=tot;
}
}
stack<int>s;
int dfs(int x){
dfn[x]=low[x]=++cntt;vis[x]=1;
s.push(x);
for(int j=head[x];j;j=a[j].nxt){
int vv=a[j].to;
if(!dfn[vv]){
int lowv=dfs(vv);
low[x]=min(low[x],lowv);
}
else{
if(vis[vv]){
low[x]=min(low[x],low[vv]);
}
}
}
if(dfn[x]==low[x]){
cntcol++;colour[x]=cntcol;cnt[cntcol]++;
vis[x]=0;
sta[cntcol][1]=x;
while(s.top()!=x){
colour[s.top()]=cntcol;cnt[cntcol]++;
vis[s.top()]=0;sta[cntcol][cnt[cntcol]]=s.top();
s.pop();
}s.pop();
maxcnt=max(maxcnt,cnt[cntcol]);
}
return low[x];
}
void tarjan(){
for(int i=1;i<=n;i++){
if(!dfn[i])dfs(i);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
tarjan();
printf("%d\n",maxcnt);
for(int i=1;i<=cntcol;i++){
if(cnt[i]==maxcnt){
sort(sta[i]+1,sta[i]+1+maxcnt);
for(int j=1;j<=cnt[i];j++)printf("%d ",sta[i][j]);
printf("\n");
return 0;
}
}
}
#include<bits/stdc++.h>//tarjan 缩点
using namespace std;
int n,m,tot,cnt,dep;
struct node{
int to,nxt;
}a[200007];
int head[200005],dfn[200005],q[200005],low[200005],colour[200005];
bool vis[200005],use[200005];
stack<int>s;
int x[200005],y[200005];
int newq[200005],dp[200005];
void add(int u,int v){
a[++tot].to=v;a[tot].nxt=head[u];
head[u]=tot;
}
int tarjan(int u){
dep++;vis[u]=1;
s.push(u);
int lowu=dep;dfn[u]=low[u]=dep;
for(int j=head[u];j;j=a[j].nxt){
int vv=a[j].to;
if(!dfn[vv]){
int lowv=tarjan(vv);
lowu=min(lowu,lowv);
}else{//huidao zuxian
if(vis[vv])
lowu=min(lowu,low[vv]);
}
}
low[u]=lowu;
if(low[u]==dfn[u]){//buneng huidao zhiqian
cnt++;
colour[u]=cnt;vis[u]=0;
newq[cnt]+=q[u];
while(s.top()!=u){
colour[s.top()]=cnt;
newq[cnt]+=q[s.top()];
vis[s.top()]=0;
s.pop();
}s.pop();
}
return lowu;
}
void work(){
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
}
//void print(){
// for(int i=1;i<=n;i++)printf("%d\n",colour[i]);
//}
void search(int u){
if(dp[u])return;
dp[u]=newq[u];
int qwq=0;
for(int j=head[u];j;j=a[j].nxt){
int vv=a[j].to;
if(!dp[vv])search(vv);
qwq=max(qwq,dp[vv]);
}dp[u]+=qwq;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&q[i]);
for(int i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
add(x[i],y[i]);
}work();
//print();
int ans=0;
memset(head,0,sizeof head);
memset(a,0,sizeof a);
tot=0;
for(int i=1;i<=m;i++)
if(colour[x[i]]!=colour[y[i]])add(colour[x[i]],colour[y[i]]);
for(int i=1;i<=cnt;i++){
if(!dp[i]){
search(i);
ans=max(ans,dp[i]);
}
}
printf("%d\n",ans);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m,tot,cnt,dep;
struct node{
int to,nxt;
}a[200007];
int head[20005],dfn[20005],low[20005];
bool iscut[20005];
void add(int u,int v){
a[++tot].to=v;a[tot].nxt=head[u];
head[u]=tot;
}
void tarjan(int u,int fa){
int ch=0;dep++;
dfn[u]=low[u]=dep;
for(int j=head[u];j;j=a[j].nxt){
int vv=a[j].to;
if(!dfn[vv]){
ch++;//yiding shi erzi
tarjan(vv,u);
low[u]=min(low[u],low[vv]);
if(low[vv]>=dfn[u])iscut[u]=1;//zhiyao you yige huibulai jiushi gedian
}else{//huidao zuxian
if(vv!=fa&&dfn[vv]<dfn[u])
low[u]=min(low[u],low[vv]);
}
}
if(fa==-1&&ch==1)iscut[u]=0;
if(fa==-1&&ch>=2)iscut[u]=1;
}
void work(){
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i,-1);
}
}
void print(){
for(int i=1;i<=n;i++)
if(iscut[i])cnt++;
printf("%d\n",cnt);
for(int i=1;i<=n;i++)
if(iscut[i])printf("%d ",i);
}
int main(){
scanf("%d%d",&n,&m);
while(m--){
int u,v;scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}work();
print();
return 0;
}
二、几道例题
·洛谷 P1407 稳定婚姻
#include<bits/stdc++.h>
using namespace std;
const int MAXM=100007;
const int MAXN=10007;
struct sth{
int to,nxt;
}a[MAXM];
map<string,int>G;
map<string,int>B;
int n,m,tot,head[MAXN];
void add(int u,int v){
a[++tot].to=v;a[tot].nxt=head[u];
head[u]=tot;
}
int dfn[MAXN],low[MAXN],colour[MAXN],cnt[MAXN],cntt,cntcol;
bool vis[MAXN];
stack<int>s;
void tarjan(int x){
dfn[x]=low[x]=++cntt;vis[x]=1;
s.push(x);
for(int j=head[x];j;j=a[j].nxt){
int vv=a[j].to;
if(!dfn[vv]){
tarjan(vv);
low[x]=min(low[x],low[vv]);
}
else{
if(vis[vv])low[x]=min(low[x],low[vv]);
}
}
if(dfn[x]==low[x]){
cntcol++;colour[x]=cntcol;
cnt[cntcol]++;vis[x]=0;
while(s.top()!=x){
colour[s.top()]=cntcol;
cnt[cntcol]++;vis[s.top()]=0;
s.pop();
}s.pop();
}
}
void work(){
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
}
int main(){
scanf("%d",&n);
string a,b;
for(int i=1;i<=n;i++){
cin>>a>>b;
G[a]=i;B[b]=i;
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
cin>>a>>b;
add(G[a],B[b]);
}
work();
for(int i=1;i<=n;i++){
if(cnt[colour[i]]>1)printf("Unsafe\n");
else printf("Safe\n");
}
return 0;
}
·洛谷 P2746 [USACO5.3]校园网Network of Schools
//整张图强连通
//嘤嘤嘤
#include<bits/stdc++.h>
using namespace std;
const int MAXN=105;
const int MAXM=10005;
struct sth{
int to,nxt;
}a[MAXM];
int n,m,tot,head[MAXN];
void add(int u,int v){
a[++tot].to=v;a[tot].nxt=head[u];
head[u]=tot;
}
int dfn[MAXN],low[MAXN],cntt,colour[MAXN],cntcol,cnt[MAXN];
int ans1,ans2,cntr,cntc;
bool rudu[MAXN],chudu[MAXN],vis[MAXN];
stack<int>s;
int tarjan(int x){
dfn[x]=low[x]=++cntt;vis[x]=1;s.push(x);
for(int j=head[x];j;j=a[j].nxt){
int vv=a[j].to;
if(!dfn[vv]){
int lowv=tarjan(vv);
low[x]=min(low[x],lowv);
}
else{
if(vis[vv]){
low[x]=min(low[x],low[vv]);
}
}
}
if(dfn[x]==low[x]){
cntcol++;colour[x]=cntcol;
cnt[cntcol]++;vis[x]=0;
while(s.top()!=x){
colour[s.top()]=cntcol;
cnt[cntcol]++;vis[s.top()]=0;
s.pop();
}s.pop();
}
return low[x];
}
void work(){
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
//solve-A
for(int i=1;i<=n;i++){
for(int j=head[i];j;j=a[j].nxt){
if(colour[i]==colour[a[j].to])continue;
rudu[colour[a[j].to]]=1;
}
}
for(int i=1;i<=cntcol;i++){
if(!rudu[i])ans1++;
}
printf("%d\n",ans1);
//solve-B
cntr=ans1;
for(int i=1;i<=n;i++){
for(int j=head[i];j;j=a[j].nxt){
if(colour[i]==colour[a[j].to])continue;
chudu[colour[i]]=1;
}
}
for(int i=1;i<=cntcol;i++){
if(!chudu[i])cntc++;
}
ans2=max(cntr,cntc);
if(cntcol==1)printf("0\n");
else printf("%d\n",ans2);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int tmp;scanf("%d",&tmp);
while(tmp){
add(i,tmp);
scanf("%d",&tmp);
}
}
work();
return 0;
}
·洛谷 P3469 [POI2008]BLO-Blockade
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100007;
const int MAXM=1000007;
#define ll long long
ll ans[MAXN];
struct sth{
ll to,nxt;
}a[MAXM];
ll n,m,tot,head[MAXN];
void add(ll u,ll v){
a[++tot].to=v;a[tot].nxt=head[u];
head[u]=tot;
}
ll dfn[MAXN],low[MAXN],cntt,size[MAXN];
bool vis[MAXN],iscut[MAXN];
void tarjan(ll x,ll fa){
size[x]=1;
ll sum=0;
dfn[x]=low[x]=++cntt;
ll ch=0;
for(ll j=head[x];j;j=a[j].nxt){
ll vv=a[j].to;
if(!dfn[vv]){
ch++;
tarjan(vv,x);size[x]+=size[vv];
low[x]=min(low[x],low[vv]);
if(low[vv]>=dfn[x]){
iscut[x]=1;sum+=size[vv];
ans[x]+=size[vv]*(n-size[vv]);
}
}
else{
if(vv!=fa&&dfn[vv]<dfn[x]){
low[x]=min(low[x],dfn[vv]);
}
}
}
if(fa==-1&&ch==1)iscut[x]=0;
if(fa==-1&&ch>1)iscut[x]=1;
if(!iscut[x])ans[x]=2*(n-1);
else ans[x]+=(n-sum-1)*(sum+1)+(n-1);
}
void work(){
for(ll i=1;i<=n;i++){
if(!dfn[i])tarjan(i,-1);
}
}
int main(){
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++){
ll u,v;
scanf("%lld%lld",&u,&v);
add(u,v);add(v,u);
}
work();
for(ll i=1;i<=n;i++){
printf("%lld\n",ans[i]);
}
return 0;
}