[USACO15JAN] Grass identification Grass Cownoisseur, Luo Guzhi improvement experience, strong connected component

The subject

      [USACO15JAN] Grass identification Grass Cownoisseur

      This question seems to be very annoying, because it has to deal with the "reverse walk once" thing.

      But we seem to be able to enumerate it~~

      The point is to be shortened first, because both nodes in the ring can reach each other.

      After shrinking the point, we thought, how can we meet this condition.

      In fact, I just want to build an edge and then form a ring.

      Then the size of the ring formed after reversing an edge is equal to the maximum distance from the connected block where 1 is located to the end of the arc (starting point) plus the maximum distance from the arc head (end point) to the connected block where 1 is located.

      We can take an example. .


As shown in the figure above, we enumerate the edge i to reverse, then the size of the formed ring is equal to the sum of the sizes of the connected blocks from 1 to y, plus the sum of the sizes of the connected blocks from x to 1. (because the sides are reversed)

      The question now is how to find the maximum distance from 1 to other points (the distance is the sum of the size of connected blocks), and the maximum distance from other points to 1.

      Obviously~ SPFA twice, once ran out from the 1 forward side, and then ran out from the 1 reverse side (equivalent to other points running through the forward side to 1 point) .

      Of course, what I said above is after the shortening~DAG

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;

int n,m;
struct edge{
	int x,y,next;
}s[100010];
struct newedge{
	int x,y,next;
}p[100010];
int first[100010];
int len ​​= 0;
struct node{
	int dfn,low;
}on[100010];
int t=0;
stack<int> sta;
bool tf[100010];
int size[100010];
int where[100010];
int dis[2][100010];
int tot = 0;

void Tarjan(int x){
	t++;
	op[x].dfn=op[x].low=t;
	sta.push(x);tf[x]=true;
	for(int i=first[x];i!=0;i=s[i].next){
		int y=s[i].y;
		if(op[y].dfn==0){
			Tarjan (y);
			if (on [y] .low <on [x] .low) on [x] .low = on [y] .low;
		}
		else if(tf[y]) if(op[y].dfn<op[x].low) op[x].low=op[y].dfn;
	}
	if(op[x].dfn==op[x].low){
		to++;
		size[tot]=0;
		while(1){
			int k = sta.top ();
			get up();
			tf[k]=false;
			where[k]=tot;
			size[tot]++;
			if(k==x) break;
		}
	}
}

void ins(int z,int x,int y){
	s[z].x=x;s[z].y=y;s[z].next=first[x];first[x]=z;
}

void inss(int x,int y){
	len ++;
	p[len].x=x;p[len].y=y;p[len].next=first[x];first[x]=len;
}

void SPFA(int xx){
	queue<int> f;
	f.push(where[1]);
	memset(dis[xx],-1,sizeof(dis[xx]));
	dis[xx][where[1]]=0;
	while(!f.empty()){
		int x=f.front();
		f.pop();
		for(int i=first[x];i;i=p[i].next){
			int y=p[i].y;
			if(dis[xx][y]<dis[xx][x]+size[y]){
				dis[xx][y]=dis[xx][x]+size[y];
				f.push(y);
			}
		}
	}
}

int main(){
	scanf("%d %d",&n,&m);
	memset(first,0,sizeof(first));
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d %d",&x,&y);
		ins(i,x,y);
	}
	for(int i=1;i<=n;i++)
		if(op[i].dfn==0) Tarjan(i);
	memset(first,0,sizeof(first));
	for(int i=1;i<=m;i++)
		if(where[s[i].x]!=where[s[i].y]) inss(where[s[i].y],where[s[i].x]);
	SPFA(1);//Run reverse first
	len = 0;
	memset(first,0,sizeof(first));
	for(int i=1;i<=m;i++)
		if(where[s[i].x]!=where[s[i].y]) inss(where[s[i].x],where[s[i].y]);
	SPFA(0);//Run forward again
	int ans=0;
	for(int i=1;i<=len;i++)
		if(dis[1][p[i].x]!=-1 && dis[0][p[i].y]!=-1) ans=max(ans,dis[1][p[i].x]+dis[0][p[i].y]);
	printf("%d",ans+size[where[1]]);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324638824&siteId=291194637