Week8 assignment-C-squad leader election

topic

The university class chooses the monitor, and all N students can express their opinions.
If the opinion is AB, it means that A thinks B is suitable, and the opinions are transitive, that is, A thinks B is suitable, B thinks C is suitable, and A also thinks C is suitable. The
hard-working TT collected M opinions, I want to know the highest number of votes, and give a list of candidates, that is, all the students with the most votes, can you help him?

Input

This question has multiple sets of data. The first line T represents the number of data groups. Each group of data starts with two integers N and M (2 <= n <= 5000, 0 <m <= 30000), and the next M line contains two integers A and B (A != B) means A thinks B Suitable.

Output

For each group of data, the first line outputs "Case x:", x represents the number of the data, starting from 1, followed by the highest number of votes.
The next line outputs the serial number of the student with the most votes, separated by a space, and the space at the end of the line is not ignored!

Sample Input

2
4 3
3 2
2 0
2 1

3 3
1 0
2 1
0 2

Sample Output

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

Kosaraju

The problem solved by the algorithm
• Find all the SCCs in the directed graph
• Algorithm steps
• The first pass of dfs determines the reverse order sequence of the original graph
• The second pass of dfs traverses the
reverse graph according to the reverse order sequence • The reverse graph is about to be the original The directed edge in the graph is reversed
• Each point traversed from the starting point constitutes an SCC.
How to understand this algorithm
• The reverse graph has the same SCC as the original graph
• The reverse post-order sequence plays a role similar to topological sorting
• First Traverse S1
• Traverse S2 again
• Traverse S3 last
• Traverse the SCC of the edge connection first, and then traverse the current SC
Insert picture description here
Insert picture description here

Ideas

·Directed graph, usually consider finding the SCC convergent point, which means that mutual reachability and unidirectional reachability are considered separately
. After converging the point, it is not difficult to find that the answer is divided into two parts for the point belonging to the i-th SCC. Let SCC[i] denote the number of points in the i-th SCC
•the point in the current SCC, ans += SCC[i] – 1 (remove yourself)
• the point in other SCC
•SUM (SCC[j] ), Where j is reachable
• After a little thought, you can find that the final answer must appear in the SCC with an out-degree of 0, which can be proved by contradiction
• Therefore, we reverse the edge and perform dfs on each point with an in-degree of 0, and calculate its SUM(SCC[j]) of the reachable point, you can get the answer

data structure

int dcnt,scnt,dfn[maxn],vis[maxn],c[maxn],
 n,cnt,scc[maxn],maxx,in_scc[maxn],sum;
bool ans[maxn];
scnt:统计图中scc的个数,并记录遍历到哪个scc
dcnt:记录后序序列的序号
dfn[maxn]:记录后序序列
vis[maxn]:记录原图or反图中某个元素是否被遍历到,或者反图缩点后得到的图中某个scc是否被遍历到
c[maxn]:原图中某个元素所属的scc
n:同学数
cnt:用于统计某个scc中的元素个数
scc[maxn]:某个scc中点的个数
maxx:记录获得票数最多的scc的票数+1
in_scc[maxn]:记录某个scc在缩点图中的入度
sum:计算某个入度为0的scc的获得的票数+1,用于与maxx比较并更新maxx和ans
ans[maxn]:记录某个scc的票数是否等于maxx

algorithm

1. Use kosaraju to get the scc to which each element belongs and record it in c[] and simultaneously calculate the number of elements in each scc and record it in scc[ ].
2. Use the inverse graph and c[] to find the contraction point of scc The picture is recorded in G3, and the in-degree of each scc in the thumbnail is recorded in in_scc[]
3. Perform a deep search on G3 for all scc with in_scc[] being 0, and record the elements contained in all the sccs that arrive The sum is recorded in sum. If sum>maxx, ans will be cleared and the sum will be recorded in maxx. If sum==maxx, the ans of the scc will be set to 1. If sum<maxx, no update will be made.
4. After all in_scc traversal, the sum obtained is the final number of votes+1, output the number of votes, and traverse all points at the same time. When the value in the ans array corresponding to the scc where the point is located is set to 1, then according to the requirements of the title Output this element and get the final result.

error

1. Remember to review the code after writing:
data range (RE or MLE)
output format (PE or WA)
code logic (WA or TLE)
hack yourself
2. This question is forgotten because of traversal in dfs3 (int x) Marking as traversed leads to WA situations. Considering that because each scc may contain multiple elements, there may be multiple sides from one scc to another scc. If the traversed scc is not marked as traversed, it may cause a certain scc to be excessive Traverse

Code

#include<iostream>
#include<vector> 
#include<string.h>
using namespace std;
const int maxn=5010;
vector<int> G1[maxn],G2[maxn],G3[maxn];
int dcnt,scnt,dfn[maxn],vis[maxn],c[maxn],
 n,cnt,scc[maxn],maxx,in_scc[maxn],sum,j;
bool ans[maxn];
void dfs1(int x)
{
    
    
 vis[x]=1;
 for(auto y:G1[x])
  if(!vis[y])
   dfs1(y);
 dfn[dcnt]=x;//dfn从下标0开始
 dcnt++; 
}
void dfs2(int x)
{
    
    
 cnt++;
 c[x]=scnt;
 for(auto y:G2[x])
  if(!c[y])
   dfs2(y);
}
void dfs3(int x)
{
    
    
 vis[x]=1;//忘记加导致WA、、、考虑当出现 
 sum+=scc[x]; 
 for(auto y:G3[x])
 {
    
    
  if(!vis[y])
   dfs3(y);
 }
}
void kosaraju()
{
    
    
 dcnt=scnt=0;
 maxx=0;
 memset(c,0,sizeof(c));
 memset(vis,0,sizeof(vis));
 memset(in_scc,0,sizeof(in_scc));
 for(int i=0;i<n;i++)//注意N个同学的序号是0~N-1 
  if(!vis[i]) 
   dfs1(i);
 for(int i=n-1;i>=0;i--)
  if(!c[dfn[i]])
  {
    
    
   scnt++;
   cnt=0;
   dfs2(dfn[i]); 
   scc[scnt]=cnt;  
  }
  //建立缩点后的反向图 
 for(int i=0;i<n;i++)
 {
    
    
  for(auto y:G2[i])
  {
    
    
   if(c[i]!=c[y])
   {
    
    
    G3[c[i]].push_back(c[y]);
    in_scc[c[y]]++;
   }
  }
 }
 //利用缩点后的反向图,求最大投票数 
 for(int i=1;i<=scnt;i++)
 {
    
    
  if(in_scc[i]==0)
  {
    
    
   sum=0;
   memset(vis,0,sizeof(vis));   
   dfs3(i);
   if(sum>maxx)
   {
    
    
    memset(ans,0,sizeof(ans));
    ans[i]=1;
    maxx=sum;
   }
   else if(sum==maxx)
   {
    
    
    ans[i]=1;
   }     
  }
  } 
} 
int main()
{
    
    
 ios::sync_with_stdio(false);
 int t,m,a,b;
 cin>>t;
 for(int i=1;i<=t;i++)
 {
    
    
  cin>>n>>m;  
  for(int m=0;m<n;m++)
  {
    
       
  G1[m].clear();
  G2[m].clear();
  G3[m].clear();   
  }
  while(m--)
  {
    
    
   cin>>a>>b;
   G1[a].push_back(b);
   G2[b].push_back(a);
  }
  kosaraju();
  cout<<"Case "<<i<<": "<<maxx-1<<endl;
  int flag=0;
  for(int i=0;i<n;i++)
  {
    
    
   if(ans[c[i]]==1)
   {
    
    
    if(flag==0)
    {
    
    
     cout<<i;
     flag=1;     
    }
    else
     cout<<" "<<i;     
   }
  }
  cout<<endl;
  } 
 return 0;
 } 

Guess you like

Origin blog.csdn.net/alicemh/article/details/105503565