Elección del líder del escuadrón C de asignación de la semana 8

tema

La clase de la universidad elige el monitor, y todos los estudiantes N puede expresar sus opiniones.
Si la opinión es AB, significa que A piensa B es adecuado y las opiniones son transitiva, es decir, A piensa B es adecuado, B piensa que C es adecuado, y A también piensa que C es adecuado. El
TT trabajador recogido M opiniones, quiero saber el mayor número de votos, y dar una lista de candidatos, es decir, todos los estudiantes con más votos, ¿puedes ayudarlo?

Entrada

Esta pregunta tiene varios conjuntos de datos. La primera línea T representa el número de grupos de datos. Cada grupo de datos comienza con dos números enteros N y M (2 <= n <= 5000, 0 <m <= 30000), y la siguiente línea M contiene dos números enteros A y B (A! = B) significa que A piensa B Adecuado.

Salida

Para cada grupo de datos, la primera línea da como resultado "Caso x:", x representa el número de datos, comenzando por 1, seguido del mayor número de votos.
La siguiente línea muestra el número de serie del estudiante con más votos, separado por un espacio, ¡y el espacio al final de la línea no se ignora!

Entrada de muestra

2
4 3
3 2
2 0
2 1

3 3
1 0
2 1
0 2

Salida de muestra

Caso 1: 2
0 1
Caso 2: 2
0 1 2

Kosaraju

El problema resuelto por el algoritmo
• Encuentra todos los SCC en el gráfico dirigido
• Pasos del algoritmo
• El primer paso de dfs determina la secuencia de orden inverso del gráfico original
• El segundo paso de dfs atraviesa el
gráfico inverso de acuerdo con la secuencia de orden inverso • El gráfico inverso está a punto de ser el original El borde dirigido en el gráfico se invierte
• Cada punto atravesado desde el punto de inicio constituye un SCC.
Cómo entender este algoritmo
• El gráfico inverso tiene el mismo SCC que el gráfico original
• La secuencia inversa posterior al orden juega un papel similar a la clasificación topológica
• Primero Atravesar S1
• Atravesar S2 nuevamente
• Atravesar S3 al final
• Atravesar primero el SCC de la conexión de borde y luego atravesar el SC actual
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Ideas

· Gráfica dirigida, por lo general se considera encontrar el punto convergente del SCC, lo que significa que la alcanzabilidad mutua y la alcanzabilidad unidireccional se consideran por separado
. Después de converger el punto, no es difícil encontrar que la respuesta se divide en dos partes para el punto que pertenece al i-ésimo SCC. Deje que SCC [i] denote el número de puntos en el i-ésimo SCC
• los puntos en el SCC actual, ans + = SCC [i] - 1 (elimínense usted mismo)
• los puntos en otros SCC
• SUM (SCC [j]), Donde j es alcanzable
• Después de pensar un poco, puede encontrar que la respuesta final debe aparecer en el SCC con un grado de salida de 0, lo cual se puede demostrar por contradicción
• Por lo tanto, invertimos la arista y realizamos dfs en cada punto con un grado de entrada de 0, y calculamos su SUM (SCC [j]) del punto alcanzable, puede obtener la respuesta

estructura de datos

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

algoritmo

1. Use kosaraju para obtener el scc al que pertenece cada elemento y regístrelo en c [] y simultáneamente calcule el número de elementos en cada scc y regístrelo en scc [].
2. Use el gráfico inverso yc [] para encontrar el punto de contracción de scc La imagen se registra en G3, y el grado de cada scc en la miniatura se registra en in_scc []
3. Realice una búsqueda profunda en G3 para todos los scc con in_scc [] siendo 0, y registre los elementos contenidos en todos los sccs que lleguen La suma se registra en sum. Si sum> maxx, ans se borrará y la suma se registrará en maxx. Si sum == maxx, el ans de scc se establecerá en 1. Si sum <maxx, no se realizará ninguna actualización.
4. Después de todo el recorrido in_scc, la suma obtenida es el número final de votos + 1, genera el número de votos y recorre todos los puntos al mismo tiempo. Cuando el valor en la matriz ans correspondiente al scc donde se encuentra el punto se establece en 1, entonces de acuerdo con los requisitos del tema Genere este elemento y obtenga el resultado final.

error

1. Recuerde revisar el código después de escribir:
rango de datos (RE o MLE)
formato de salida (PE o WA)
código lógico (WA o TLE)
piratear usted mismo
2. Esta pregunta se olvida debido al recorrido en dfs3 (int x) Marcar como atravesado conduce a situaciones WA. Teniendo en cuenta que debido a que cada scc puede contener múltiples elementos, puede haber múltiples lados de un scc a otro scc. Si el scc atravesado no está marcado como atravesado, puede causar que cierto scc sea excesivo atravesar

Código

#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;
 } 

Supongo que te gusta

Origin blog.csdn.net/alicemh/article/details/105503565
Recomendado
Clasificación