说明
• 对于60% 的数据, n,m在1e3内
• 对于100% 的数据, n,m在1e5内。
本弱弱上来就是一顿暴搜打,dfs n次,每次更新答案,复杂度为O(n*n),果然TLE,60分抱回家。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 7 int n,m,tot,head[100090],vis[100090],f[100090]; 8 struct node{ 9 int to,next; 10 }edge[100090]; 11 12 void add(int x,int y) 13 { 14 edge[++tot].next=head[x]; 15 head[x]=tot; 16 edge[tot].to=y; 17 } 18 19 void dfs(int x) 20 { 21 vis[x]=1; 22 for(int i=head[x];i;i=edge[i].next) 23 { 24 int v=edge[i].to; 25 if(vis[v]) continue; 26 dfs(v); 27 f[x]=max(f[x],f[v]); 28 } 29 } 30 31 int main() 32 { 33 scanf("%d%d",&n,&m); 34 for(int i=1;i<=m;i++) 35 { 36 int x=0,y=0; 37 scanf("%d%d",&x,&y); 38 add(x,y); 39 } 40 for(int i=1;i<=n;i++) f[i]=i; 41 for(int i=1;i<=n;i++) 42 { 43 dfs(i); 44 memset(vis,0,sizeof(vis)); 45 } 46 for(int i=1;i<=n;i++) printf("%d ",f[i]); 47 return 0; 48 }
然后就通往了题解。我们可以转化一下思维:求多个点到一个点,不妨从最大的点出发倒着遍历,反向连边,这样每个点只会被访问一次,复杂度O(n).
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 7 int n,m,tot,head[100090],f[100090]; 8 struct node{ 9 int to,next; 10 }edge[100090]; 11 12 void add(int x,int y) 13 { 14 edge[++tot].next=head[x]; 15 head[x]=tot; 16 edge[tot].to=y; 17 } 18 19 void dfs(int noww,int st) 20 { 21 if(f[noww]) return ; 22 f[noww]=st; 23 for(int i=head[noww];i;i=edge[i].next) 24 if(!f[edge[i].to]) dfs(edge[i].to,st); 25 } 26 27 int main() 28 { 29 scanf("%d%d",&n,&m); 30 for(int i=1;i<=m;i++) 31 { 32 int x=0,y=0; 33 scanf("%d%d",&x,&y); 34 add(y,x); 35 } 36 for(int i=n;i>=1;i--) 37 dfs(i,i); 38 for(int i=1;i<=n;i++) printf("%d ",f[i]); 39 return 0; 40 }
ps:真的这样结束了嘛?
脑洞:若求所能到达的节点编号最小???
在无向图中???
大坑待填。