题目非常简洁明了(舒服),给你一个图,求每一个点可以到达的点的最大编号是多少。一看到题目,就可以想到图的遍历(废话)
在学过的遍历方法中,深搜和光搜其实都可以,但用得多的还是深搜,所以这里我们直接尝试深搜每一个起始点,然后将图搜完(暴力60分)
#include
using namespace std;
const int MAXN=1e6+50;
int head[MAXN],tot;
struct node{
int net,to;
}e[MAXN];
void add(int u,int v){
e[++tot].net=head[u];
e[tot].to=v;
head[u]=tot;
}
int n,m;
int ans;
bool v[MAXN];
void dfs(int s){
ans=max(ans,s);
v[s]=true;
for(register int i=head[s];i;i=e[i].net){
if(v[e[i].to]==false){
dfs(e[i].to);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(register int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
for(register int i=1;i<=n;i++){
memset(v,false,sizeof v);
ans=i;
dfs(i);
printf("%d ",ans);
}
return 0;
}
然后继续想,这样做肯定是超时的,例如1可以到3,那么3可以到达的最大点就是1到达的最大点,我们想到记忆化搜索,这个做法肯定是对的,但是我不知道我为什么写炸了,只有70分,这里就不挂出来了。我们尝试用一些最短路的算法来遍历图,然后在过程中更新最大点,这样就可以A了
#include
using namespace std;
const int MAXN=1e6+50;
int head[MAXN],tot;
int n,m,dis[MAXN];
struct node{
int net,to;
}e[MAXN];
void add(int u,int v){
e[++tot].net=head[u];
e[tot].to=v;
head[u]=tot;
}
bool vis[MAXN];
inline void spfa(int k){
queueq;
q.push(k);
vis[k]=1;
int x,y;
dis[k]=k;
while(!q.empty( )){
x=q.front( );
q.pop( );
int i;
for(i=head[x];i;i=e[i].net)
if(!dis[e[i].to]){
dis[e[i].to]=k;
if(!vis[e[i].to]){
vis[e[i].to]=1;
q.push(e[i].to);
}
}
vis[x]=0;
}
}
int main(){
scanf("%d%d",&n,&m);
for(register int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(v,u);
}
for(register int i=n;i>=1;i--)
if(!dis[i])spfa(i);
for(register int i=1;i<=n;i++)
printf("%d ",dis[i]);
return 0;
}