Problem 1 Graph (graph.cpp/c/pas)
【题目描述】
给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点。
【输入格式】
第 1 行,2 个整数 N,M。 接下来 M 行,每行 2 个整数 Ui,Vi,表示边 ⟨Ui,Vi⟩。点用 1,2,...,N 编号。
【输出格式】
N 个整数 A(1),A(2),...,A(N)。
【样例输入】
4 3
1 2
2 4
4 3
【样例输出】
4 4 3 4
【数据范围】
对于 60% 的数据,1 ≤ N,K ≤ 10^3
对于 100% 的数据,1 ≤ N,M ≤ 10^5。
题解:
暴力+错误tarjan缩点
先写的缩点,对拍半天,补了n个漏洞,跑大数据平均10个WA3个
两个程序就一起交了。略丑。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define N 100008 using namespace std; int n,m,sumedge; queue<int>q; int head[N]; int ans[N],vis[N]; int top,tim,sumcol; int low[N],dfn[N],Stack[N],instack[N],bel[N],mx[N]; int cd[N],rd[N]; inline int read(){ char ch=getchar();int x=0,f=1; for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return x*f; } struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[N]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void bfs(int x){ memset(vis,0,sizeof(vis)); vis[x]=true; while(!q.empty())q.pop(); q.push(x); while(!q.empty()){ int now=q.front();q.pop(); ans[x]=max(ans[x],now); for(int i=head[now];i;i=edge[i].nxt){ int v=edge[i].y; if(!vis[v]){ q.push(v);vis[v]=1; } } } } void tarjian(int x){ low[x]=dfn[x]=++tim; Stack[++top]=x;instack[x]=true; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(instack[v])low[x]=min(low[x],dfn[v]); else if(!dfn[v]){ tarjian(v); low[x]=min(low[x],low[v]); } } if(low[x]==dfn[x]){ sumcol++; while(Stack[top+1]!=x){ bel[Stack[top]]=sumcol; instack[Stack[top]]=false; mx[sumcol]=max(mx[sumcol],Stack[top]); top--; } } } void dfs(int x){ for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(bel[x]==bel[v])continue; dfs(v); ans[bel[x]]=max(ans[bel[x]],ans[bel[v]]); } return; } int main(){ freopen("graph.in","r",stdin); freopen("graph.out","w",stdout); n=read();m=read(); for(int i=1;i<=m;i++){ int x,y; x=read();y=read(); add(x,y); } if(n<=3000){ for(int i=1;i<=n;i++)bfs(i); for(int i=1;i<=n;i++)printf("%d ",ans[i]); return 0; fclose(stdin);fclose(stdout); } for(int i=1;i<=n;i++)if(!dfn[i])tarjian(i); for(int x=1;x<=n;x++){ for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(bel[v]!=bel[x]) cd[bel[x]]++,rd[bel[v]]++; } } for(int i=1;i<=n;i++)ans[bel[i]]=mx[bel[i]]; for(int i=1;i<=n;i++)if(!rd[bel[i]])dfs(i); for(int i=1;i<=n;i++)printf("%d ",max(ans[bel[i]],mx[bel[i]])); fclose(stdin);fclose(stdout); return 0; }