Tarjan求强连通分量板子

CJOJ P1419 [WZOI2011 S3模拟赛] 消息传递(PS.真心不能用vector,vector450+ms,链式前向星180+ms)

#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
const int maxn=100001;
const int maxm=200001;
using namespace std;
inline int gi() {
	int p=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch<='9'&&ch>='0')p=p*10+ch-'0',ch=getchar();
	return p;
}
int n,m;
stack<int>D;
int Now=0,vis[maxn],Index=0;
bool ans[maxn];
int low[maxn],dfn[maxn];
bool yes[maxn];
int fir[maxn],dis[maxm],nxt[maxm];
inline void init() {
	n=gi(),m=gi();
	int a,b;
	for(int i=1;i<=m;i++) {
		a=gi(),b=gi();
		nxt[i]=fir[a];
		fir[a]=i;
		dis[i]=b;
	}
}
inline void Tarjan(int now) {
	dfn[now]=low[now]=++Index;
	vis[now]=Now;
	D.push(now),yes[now]=1;
	for(int i=fir[now]; i; i=nxt[i]) {
		register int t=dis[i];
		if(!vis[t]) {
			Tarjan(t);
			low[now]=min(low[t],low[now]);
		} else if(yes[t])low[now]=min(dfn[t],low[now]);
	}
	if(low[now]==dfn[now]) {
		if(D.top()==now)yes[D.top()]=0,D.pop();
		else {
			while(D.top()!=now) {
				ans[D.top()]=1;
				yes[D.top()]=0;
				D.pop();
			}
			ans[now]=1;
			yes[now]=0;
			D.pop();
		}
	}
}
inline void work() {
	for(int i=1; i<=n; i++)if(!vis[i])++Now,Tarjan(i);
}
inline void out() {
	for(int i=1; i<=n; i++)
		if(ans[i])printf("T\n");
		else printf("F\n");
}
int main() {
	init();
	work();
	out();
	return 0;
}


CJOJ  P2275 篮球队员的通讯问题

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 10010
#define maxm 800010
int nxt[maxm],dis[maxm],fir[maxn];
int Stack[maxn],top=0,low[maxn],dfn[maxn],index=0;
int vis[maxn],s=0;	
bool yes[maxn];
int n,sum=0;
vector<int>ans[10001];
inline int gi() {
	int x=0;
	char p=getchar();
	while(p>'9'||p<'0')p=getchar();
	while(p<='9'&&p>='0')x=x*10+p-'0',p=getchar();
	return x;
}
inline void init() {
	n=gi();
	int a,b;
	for(int i=1; scanf("%d%d",&a,&b)==2; i++) {
		nxt[i]=fir[a];
		dis[i]=b;
		fir[a]=i;
	}
}
inline void Tarjan(int now,int s) {
	vis[now]=s,yes[now]=1;
	Stack[++top]=now;
	low[now]=dfn[now]=++index;
	for(int i=fir[now]; i; i=nxt[i])
		if(!vis[dis[i]]) {
			Tarjan(dis[i],s);
			low[now]=min(low[now],low[dis[i]]);
		} else if(yes[dis[i]])low[now]=min(low[now],dfn[dis[i]]);
	if(low[now]==dfn[now]) {
		++sum;
		while(Stack[top]^now&&top)ans[sum].push_back(Stack[top]),yes[Stack[top--]]=0;
		ans[sum].push_back(Stack[top]),yes[Stack[top--]]=0;
	}
}
inline bool cmp(const vector<int>a,const vector<int>b){
	return a[0]<b[0];
}
inline void out() {
	printf("%d\n",sum);
	for(int i=1; i<=sum; i++)
		sort(ans[i].begin(),ans[i].end());
	sort(ans+1,ans+sum+1,cmp);
	for(int i=1; i<=sum; i++) {
		for(int j=0; j<ans[i].size(); j++)
			printf("%d ",ans[i][j]);
		printf("\n");
	}
}
int main() {
	init();
	for(int i=1; i<=n; i++)if(!vis[i]) {
			Tarjan(i,++s);
			top=0;
		}
	out();
	return 0;
}

CJOJP1292 【HAOI2006 】受欢迎的牛

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 10010
#define maxm 100010
int nxt[maxm],dis[maxm],fir[maxn];
int Stack[maxn],top=0,low[maxn],dfn[maxn],index=0,K[maxn];
int n,m,sum=0;
int ans=-1,ansnum=0;
bool yes[maxn];
inline int gi() {
	int x=0;
	char p=getchar();
	while(p>'9'||p<'0')p=getchar();
	while(p<='9'&&p>='0')x=x*10+p-'0',p=getchar();
	return x;
}
inline void init() {
	n=gi(),m=gi();
	int a,b;
	for(int i=1; i<=m; i++) {
		a=gi(),b=gi();
		nxt[i]=fir[a];
		dis[i]=b;
		fir[a]=i;
	}
}
inline void Tarjan(int now) {
	yes[now]=1;
	Stack[++top]=now;
	low[now]=dfn[now]=++index;
	for(int i=fir[now]; i; i=nxt[i])
		if(!dfn[dis[i]]) {
			Tarjan(dis[i]);
			low[now]=min(low[now],low[dis[i]]);
		} else if(yes[dis[i]])low[now]=min(low[now],dfn[dis[i]]);
	if(low[now]==dfn[now]){
			++sum;
			int T=top;
			while(Stack[top]^now&&top)yes[Stack[top]]=0,K[Stack[top--]]=sum;
			yes[Stack[top]]=0,K[Stack[top--]]=sum;
			for(int i=top+1; i<=T; i++)
				for(int j=fir[Stack[i]]; j; j=nxt[j])
					if(K[dis[j]]!=sum)return;
			ans=sum,ansnum++;
		}
}
inline void out() {
	if(ans==-1||ansnum>1)printf("0\n");
	else {
		ansnum=0;
		for(int i=1; i<=n; i++)if(K[i]==ans)ansnum++;
		printf("%d",ansnum);
	}
}
int main() {
	init();
	for(int i=1; i<=n; i++)if(!dfn[i])Tarjan(i),top=0;
	out();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值