Tarjan相關(強連通分量,割點,縮點)
阿新 • • 發佈:2018-11-04
一、先上模板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;
}