Título: Elección del líder de la clase
Tema: El
líder de la clase de la clase universitaria, N estudiantes pueden expresar sus opiniones.
Si la opinión es AB, significa que A piensa que B es apropiado, y la opinión es transitiva, es decir, A piensa que B es adecuado y B piensa que C es adecuado, entonces A también piensa C. es adecuado. El
trabajador TT ha reunido M opiniones y quiere saber el número máximo de votos, y da una lista de candidatos, es decir, todos los estudiantes con más votos, ¿puede ayudarlo?
Entrada:
Existen múltiples conjuntos de datos para esta pregunta. La primera línea T representa el número de grupos de datos. Cada conjunto de datos comienza con dos enteros N y M (2 <= n <= 5000, 0 <m <= 30000), luego hay M filas que contienen dos enteros A y B (A! = B) significa que A piensa B Adecuado
Salida:
para cada conjunto de datos, la primera línea emite "Caso x:", x indica el número de datos, comenzando desde 1, seguido del mayor número de votos.
¡La siguiente línea muestra el número del estudiante con más votos, separados por espacios, y no ignora los espacios al final de la línea!
Muestra:
Ideas para resolver problemas: este problema puede tratar a los estudiantes como puntos, y a-> b votar como composición de borde, luego encontrar componentes conectados fuertes a través de scc, y el valor de cada punto en cada componente es el número de puntos -1; Después, los puntos se acortan, y cada componente conectado fuerte es un punto (después del punto de contracción también hay un diagrama de secuencia inversa); si hay a-> b, entonces el número de votos para cada punto en b + = el número de puntos en un Se puede usar una vez), en este momento, puede ejecutar todo el gráfico con un punto de 0 grados, encontrar el más grande que sea necesario y luego enumerar el punto medio del punto de contracción;
Código:
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
int n,m;
vector<int> g[5005],g1[5005],g0[5005];
int in[5005],out[5005],d[5005],f[5005],dcnt=0,tcnt=0,vis[5005],ans[5005],maxn=0,jilu[5005];
void dfs(int x)//scc正逆图各跑一遍
{
vis[x]=1;
for(int i=0;i<g[x].size();i++)
{
if(!vis[g[x][i]])
{
dfs(g[x][i]);
}
}
d[++dcnt]=x;
}
void dfs1(int x)
{
f[x]=tcnt;
for(int i=0;i<g0[x].size();i++)
{
if(!f[g0[x][i]])
{
dfs1(g0[x][i]);
}
}
}
void dfs2(int x,int y)//从入度为0的点开始跑
{
vis[x]=1;
for(int i=0;i<g1[x].size();i++)
{
int to=g1[x][i];
if(!vis[to])
{
jilu[y]+=(jilu[to]+1);//加上,这里y是入度为0的点,所以修改它的票数不影响结果
dfs2(to,y);
}
}
}
void suodian()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<g0[i].size();j++)
{
if(f[i]!=f[g0[i][j]])//缩点,逆序图
{
g1[f[i]].push_back(f[g0[i][j]]);
in[f[g0[i][j]]]++;
}
}
}
}
void sousuo()//搜索入度为0的点之后dfs
{
for(int i=1;i<=tcnt;i++)
{
if(in[i]==0)
{
memset(vis,0,sizeof(vis));
dfs2(i,i);
}
}
}
int main()
{
int p;
scanf("%d",&p);
int s=0;
while(p--)
{
s++;
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(d,0,sizeof(d));
memset(f,0,sizeof(f));
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
memset(jilu,0,sizeof(jilu));
dcnt=tcnt=maxn=0;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)
{
g[i].clear();
g1[i].clear();
g0[i].clear();
}
int x,y;
for(int i=0;i<m;i++)//正逆图
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
g0[y].push_back(x);
}
for(int i=0;i<n;i++)
{
if(!vis[i])
{
dfs(i);
}
}
for(int i=n;i>=1;i--)
{
if(!f[d[i]])
{
tcnt++;
dfs1(d[i]);
}
}
for(int i=0;i<n;i++)//初始化
{
jilu[f[i]]++;
}
for(int i=1;i<=tcnt;i++)
{
jilu[i]--;
}
suodian();
sousuo();
for(int i=1;i<=tcnt;i++)//找最大的那个
{
maxn=max(maxn,jilu[i]);
}
printf("Case %d: %d\n",s,maxn);
int ff=0;
for(int i=0;i<n;i++)//扫一遍
{
if(jilu[f[i]]==maxn)
{
if(ff==0)
{
ff=1;
}else
{
printf(" ");
}
printf("%d",i);
}
}
printf("\n");
}
}
/*
8
8 11
0 1
1 2
2 0
2 7
6 2
6 7
3 0
3 6
4 3
6 5
5 4
*/