刚学OI的萌新第二个点不过,数组开两倍就过了求解答QwQ
查看原帖
刚学OI的萌新第二个点不过,数组开两倍就过了求解答QwQ
340632
Cry_For_theMoon楼主2020/8/23 16:12

rt

我和题解不太一样,没有删点啊,建新图啊,建图的时候就反着建的,然后算法里也没有加别的边。但还是要开2倍大小不然第二个点WA了(不是应该RE的说吗?

求大佬解答

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=2e4+10,MAXM=4e5+10,INF=2e9;
struct Edge{
	int u,v;
}edge[MAXM];
int first[MAXN],next[MAXM],tot;
int n,m,s,t;
int arrive[3][MAXN],check[MAXN];
void addedge(int u,int v){
	tot++;
	edge[tot].u=u;edge[tot].v=v;
	next[tot]=first[u];
	first[u]=tot;
}
void tryarrive(int start,int ans[]){
	int vis[MAXN];
	queue<int>q;
	vis[start]=1;
	ans[start]=1;
	q.push(start);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int j=first[u];j;j=next[j]){
			int v=edge[j].v;
			if(!vis[v]){
				vis[v]=1;
				ans[v]=1;
				q.push(v);
			}
		}
	}
}
void findtrail(int start,int ans[]){
	for(int i=1;i<=n;i++){
		ans[i]=INF;
	}
	ans[start]=0;
	queue<int>q;
	if(check[start])q.push(start);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int j=first[u];j;j=next[j]){
			int v=edge[j].v;
			if(!check[v])continue;
			if(ans[u]+1<ans[v]){
				ans[v]=ans[u]+1;
				q.push(v);
			}
		}
	}
} 
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		addedge(y,x);
	}
	cin>>s>>t;
	//预处理每个点和s/t是否连通 
	tryarrive(s,arrive[0]);
	tryarrive(t,arrive[1]);
	//预处理这个点是否能选
	for(int i=1;i<=n;i++){
		check[i]=1;
	}
	for(int i=1;i<=n;i++){
		int& u=i;
		if(arrive[0][u] || arrive[1][u])continue;
		for(int j=first[u];j;j=next[j]){
			int v=edge[j].v;
			check[v] = 0;
		}
	} 
	//找一条从t到s的路径(因为倒着建图了)
	findtrail(t,arrive[2]);
	if(arrive[2][s]==INF){
		printf("-1");
	}else{
		printf("%d",arrive[2][s]);
	}
	return 0;
}
2020/8/23 16:12
加载中...