P7516 - [provincial selection joint examination volume 2021A/B] graph function [bfs]

Posted by youropensource on Wed, 24 Nov 2021 20:37:56 +0100

Topic

Title Link: https://www.luogu.com.cn/problem/P7516

General idea of the topic

Lazy, just copy the meaning of the question
For a directed graph \ (G \) with \ (n \) points \ (m \) edges (vertices are numbered from \ (1 \sim n \), define the function \ (f(u, G) \):

  1. Initialization return value \ (cnt = 0 \), figure \ (G'= G \).
  2. Enumerate the vertices \ (v \) in order from \ (1 \) to \ (n \). If the paths from \ (u \) to \ (v \) and from \ (v \) to \ (u \) exist in the current graph \ (G '; \), delete \ (cnt + 1 \) and delete the vertex \ (v \) and its related edges in the graph \ (G'; \).
  3. After step \ (2 \), the return value \ (cnt \) is the function value.

Now, given a directed graph \ (G \), please find the value of \ (h(G) = f(1, G) + f(2, G) + \cdots + f(n, G) \).

Further, note that the figure after deleting the \ (1 \) to \ (I \) edges (given in the input order) is \ (G_i \) (\ (1 \le i \le m \)), please find out the values of all \ (h(G_i) \).

\(1\leq n\leq 10^3,1\leq m\leq 2\times 10^5\)

Problem solving ideas

Any method that does not follow the inertial thinking can solve this problem

The meaning of this deletion is very unclear. On the contrary, it is much simpler to directly change it to addition.

Another problem is that it is not necessary to judge whether to delete points:

Assuming that for the starting point \ (u \) can go to \ (v \) and \ (v \) cannot go to \ (u \), it is obvious that there is no node \ (x \) so that \ (u \) can go to \ (x \) and \ (x \) can go to \ (u \), and \ (v \) is the necessary point of these paths, because \ (v \) must be on this ring, then \ (v \) can obviously go to \ (u \).

Therefore, now whether \ (f(u,G) \) can count \ (v \) becomes to judge whether there is a ring of \ (u\rightarrow v\rightarrow u \), so that the number of all points on the path is not less than \ (min(u,v) \).

Then consider the time when two point pairs \ ((u,v) \) make their first contribution after adding edges. The weight of each edge is set as the joining time. This time is a path of \ (u\rightarrow v\rightarrow u \) without passing through points with a number less than \ (min(u,v) \).

In this way, Flody has the algorithm of \ (O(n^3) \).

Then we thought for a long time and felt that the shortest path would not work. At this time, we need to abandon the idea of inertial thinking. We consider another more violent approach. We add edges every time and judge the connection between each point violently. We found that such time complexity is \ (O(nm^2) \).

Then, we still consider another possibility. Instead of enumerating edges, we enumerate the starting point \ (u \) of the statistical answer, and then add one edge \ ((x,y) \) at a time. If \ (u \) can go to \ (x \) and cannot go to \ (Y \), then \ (u \) can go to \ (Y \) and start from \ (Y \) \ (bfs \) all other nodes that have not gone through, It should be noted that both sides of the edge are traversed, so it can be deleted directly.

This time complexity is \ (O(n(n+m)) \), which can be solved by this problem.

Need card Chang

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=1e3+10,M=2e5+10;
struct node{
	int to,next;
}a[M];
int n,m,f[N][N],g[N][N];
int ex[M],ey[M],ans[M];
vector<int> G[N],D[N];queue<int> q;
void bfs(int x,int s,int w){
	q.push(x);
	while(!q.empty()){
		int x=q.front();q.pop();f[s][x]=w;
		for(int i=0;i<G[x].size();i++)
			if(!f[s][G[x][i]])q.push(G[x][i]);
		G[x].clear();
	}
	return;
}
void bgs(int x,int s,int w){
	q.push(x);
	while(!q.empty()){
		int x=q.front();q.pop();g[s][x]=w;
		for(int i=0;i<D[x].size();i++)
			if(!g[s][D[x][i]])q.push(D[x][i]);
		D[x].clear();
	}
	return;
}
int main()
{
	scanf("%d%d",&n,&m);m++;
	for(int i=2;i<=m;i++)
		scanf("%d%d",&ex[i],&ey[i]);
	reverse(ex+2,ex+1+m);
	reverse(ey+2,ey+1+m);
	for(int x=1;x<=n;x++){
		for(int i=1;i<=n;i++)G[i].clear();
		for(int i=1;i<=n;i++)D[i].clear();
		f[x][x]=g[x][x]=1;
		for(int i=2;i<=m;i++){
			if(ex[i]<x||ey[i]<x)continue;
			if(f[x][ex[i]]&&!f[x][ey[i]])bfs(ey[i],x,i);
			else if(!f[x][ex[i]]&&!f[x][ey[i]])G[ex[i]].push_back(ey[i]);
			if(g[x][ey[i]]&&!g[x][ex[i]])bgs(ex[i],x,i);
			else if(!g[x][ey[i]]&&!g[x][ex[i]])D[ey[i]].push_back(ex[i]);
		}
	}
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j++)
			if(f[i][j]&&g[i][j])
				ans[max(f[i][j],g[i][j])]++;
	for(int i=1;i<=m;i++)ans[i]+=ans[i-1];
	reverse(ans+1,ans+1+m);
	for(int i=1;i<=m;i++)
		printf("%d ",ans[i]);
	return 0;
}

Topics: search engine