WEEK8 Weekly Job-kosaraju Simulation-DFS Sequence_Class Leader Election

WEEK8 Weekly Job-kosaraju Simulation-DFS Sequence_Class Leader Election

1. Topic

1. Brief description

When choosing a monitor in a university class, N students can express their opinions. If the opinions are A B, A thinks B is suitable and B thinks C is suitable, A also thinks C is suitable and hard-working TT collects M opinions. Want to know the maximum number of votes and give a list of candidates, that is, all the students who get the most votes. Can you help him?

2. Input Format

This question has multiple sets of data.The first row T represents the number of data groups.Each set of data starts with two integers N and M (2 <= n <= 5000, 0 <m <= 30000), followed by an M line containing two integers A and B (A!= B) indicating that A thinks B is appropriate.

3. Output Format

For each set of data, the first line outputs "Case x:", where X represents the number of data, starting with 1, followed by the highest number of votes.The next line outputs the number of the students who get the most votes, separated by spaces, without ignoring the space at the end of the line!

4. Samples

Input

2
4 3
3 2
2 0
2 1

3 3
1 0
2 1
0 2

Output

Case 1: 2
0 1
Case 2: 2
0 1 2

2. Algorithms

Main ideas

First, all SCC s (strongly connected subgraphs) are computed using kosaraju simulation.Each subgraph is then reduced to a point to form a thumbnail.

This question is mainly about ideas, the code is not really hard to write, mainly through multiple dfs.

3. Code

#include<iostream>
#include<cstring>
#include<algorithm> 
#include<string>
#include<cstdlib>
#include<queue>
#define mem(s,v) memset(s,v,sizeof(s))
using namespace std;
struct edge{
	int to,next;
} ed1[30010],ed2[30010],eds[30010],edsf[30010];
int head1[5010],head2[5010],heads[5010],headsf[5010];
int num_edge = 0;

int vis[5010];
int c[5010];
int seq[5010];//You don't need to empty each group, just set num_seq to 0 
int scnt = 0;
int num_seq = 0;
int sum[5010];

void add(int from,int to,edge ed[],int head[]){
	ed[++num_edge].next = head[from];
	head[from] = num_edge;
	ed[num_edge].to = to;
}
void dfs_seq(int s){
	vis[s] = 1;
	for(int i=head1[s];i;i=ed1[i].next){
		if(!vis[ed1[i].to])
			dfs_seq(ed1[i].to);
	}
	seq[num_seq] = s;
	num_seq++;
}
void dfs2(int s){
	vis[s] = scnt;
	sum[scnt]++;
	for(int i=head2[s];i;i=ed2[i].next){
		if(!vis[ed2[i].to])
			dfs2(ed2[i].to);
	}
}
void dfs3(int s,int& ssum,int flag){
	ssum += sum[s];
	c[s] = flag;
	for(int i=headsf[s];i;i=edsf[i].next){
		if(c[edsf[i].to]!=flag)
			dfs3(edsf[i].to,ssum,flag);
	}
}
 
int main(){
	int t;
	scanf("%d",&t);
	for(int tt=1;tt<=t;tt++){//Don't forget to see if there are multiple sets of data!
		int n,m;
		scanf("%d%d",&n,&m);
		//mem(vis,0);
		for(int i=0;i<n;i++){
			vis[i] = 0;
			head1[i] = 0;
			head2[i] = 0;
		}
		//mem(head1,0);
		//mem(head2,0);
		
		num_edge = 0;
		int i;
		for(i=0;i<m;i++){//O(m)
			int a,b;
			scanf("%d%d",&a,&b);
			add(a,b,ed1,head1);
			num_edge--;
			add(b,a,ed2,head2);
		}
		for(int i=0;i<n;i++)//O(n)
			if(!vis[i]) dfs_seq(i);
		
		for(i=0;i<=n+10;i++){//The sum cannot be i<n when it reassigns to zero here, because the sum is a 1-scnt, so it should be [1,n] instead of [1,n] 
			vis[i] = 0;
			sum[i] = 0;	
		}
		num_seq = 0;
		scnt = 0;
		for(i=n-1;i>=0;i--)//Inverse backward traversal of the inverse //O(n)
			if(!vis[seq[i]]) scnt++,dfs2(seq[i]);
		
		//With reverse thumbnails, there are scnt points//O(m)
		num_edge = 0;
		for(i=0;i<=scnt;i++){
			heads[i] = 0;
			headsf[i] = 0;
		}
		for(i=0;i<n;i++){
			for(int j=head2[i];j;j=ed2[j].next){
				if(vis[i]==vis[ed2[j].to]) continue;
				add(vis[i],vis[ed2[j].to],edsf,headsf);
				num_edge--;
				add(vis[ed2[j].to],vis[i],eds,heads);
			}
		}
		
		//dfs thumbnail with point number starting from 1 
		for(i=0;i<=scnt;i++) c[i] = 0;
		int ssum = 0;
		int maxi = 0;
		int smax = 0;
		for(i=1;i<=scnt;i++){
			if(heads[i]==0){//Indentation of 0 in inverse indentation 
				ssum = 0;
				dfs3(i,ssum,i); 
				if(ssum>smax){
					smax = ssum;
					maxi = i;	
				}
				sum[i] = ssum;
			}
		}
		
		printf("Case %d: ",tt);
		printf("%d\n",smax-1);
		int count = 0;
		for(i=0;i<n;i++){
			if(sum[vis[i]]==smax){
				if(count>0) printf(" ");
				printf("%d",i);
				count++;
			}
		}
		printf("\n");
	}
	return 0;
}
Author Article 30 won 2 visits 673
follow Private letter

Posted on Mon, 04 May 2020 00:30:06 -0400 by loganbest