Ejemplo: búsqueda de ruta de red
fondo del tema
Una red en el país X utiliza varias líneas para conectar varios nodos. La comunicación entre nodos es bidireccional. Un paquete de datos importante debe reenviarse exactamente dos veces para llegar al destino por razones de seguridad. El paquete puede generarse en cualquier nodo y necesitamos saber cuántas rutas de reenvío diferentes hay en la red.
Las direcciones de origen y destino pueden ser las mismas, pero los nodos intermedios deben ser diferentes.
La red que se muestra en la siguiente figura.
1 -> 2 -> 3 -> 1 están permitidos
1 -> 2 -> 1 -> 2 o 1 -> 2 -> 3 -> 2 son ilegales.
formato de entrada
La primera línea de los datos de entrada son dos números enteros NM, que representan respectivamente el número de nodos y el número de líneas de conexión (1<=N<=10000; 0<=M<=100000).
Luego hay M líneas, y cada línea contiene dos números enteros u y v, lo que indica que los nodos u y v están conectados (1<=u, v<=N, u!=v).
Los datos de entrada garantizan que dos puntos cualesquiera estén conectados como máximo por un borde y que no haya ningún borde que se conecte automáticamente, es decir, que no haya varios bordes ni bucles automáticos.
formato de salida
Genera un número entero, que indica el número de rutas que cumplen los requisitos.
Muestras de entrada y salida
muestra de entrada
3 3 1 2 2 3 1 3
muestra de salida
6
Código de referencia
#include <iostream>
#include <cstring>
using namespace std;
#define MAXN 10005
#define MAXM 100005
struct node{
int to,next;
}edge[MAXM];
int head[MAXN];
int cnt,sum;
void add(int a,int b)
{
node E={b,head[a]};
edge[cnt]=E;
head[a]=cnt++;
}
void dfs(int from,int to,int num)
{
if (num==3)
{
sum++;
return;
}
for (int i=head[to];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if (v!=from)
{
dfs(to,v,num+1);
}
}
}
int main()
{
int n,m,a,b;
while (cin>>n>>m)
{
cnt=0;sum=0;
memset(head,-1,sizeof(head));
for (int i=0;i<m;i++)
{
cin>>a>>b;
add(a,b);
add(b,a);
}
for (int i=1;i<=n;i++)
dfs(i,i,0);
cout<<sum<<endl;
}
return 0;
}
Sacar inferencias de una instancia a otros casos——Lucha de monjes eminentes
fondo del tema
En las antiguas actividades funerarias, a menudo se invitaba a monjes eminentes a realizar rituales. Después de la ceremonia, a veces habrá un programa interesante de "Habilidades de lucha de monjes eminentes" para aliviar la atmósfera deprimida.
Los pasos generales del programa son los siguientes: primero use grano (generalmente arroz) para "dibujar" varios pasos en el suelo (que representan pagodas de nivel N). Varios monjes jóvenes se "paran" al azar en un determinado escalón. Las personas deben pararse en el escalón más alto, y los demás son opcionales. (Como se muestra en la Figura 1)
Los dos magos que participan en el juego le ordenan a un joven monje que suba cualquier cantidad de escalones, pero el joven monje que está parado en los escalones más altos los bloqueará y no podrán cruzar. Dos monjes jóvenes no pueden pararse en el mismo escalón, ni pueden moverse a escalones más bajos.
Los dos magos se turnaron para dar instrucciones y, al final, todos los monjes jóvenes inevitablemente se amontonaron en los altos escalones y ya no pudieron subir. Cuando es el turno del mago para mandar y no puede continuar moviéndose, el juego termina y el mago admite la derrota.
Para el número conocido de pasos y la posición de distribución de los monjes jóvenes, calcule cómo el mago que emitió la orden primero debe tomar una decisión para asegurar la victoria.
formato de entrada
Los datos de entrada son una línea de N enteros separados por espacios, que indican la posición del pequeño monje. El número de pasos comienza desde 1, por lo que la posición del último pequeño monje es el número total de pasos. (N<100, número total de pasos<1000)
formato de salida
La salida son dos números enteros separados por espacios en una línea: AB, lo que significa mover el pequeño monje en la posición A a la posición B. Si hay múltiples soluciones, genere la solución con el valor más pequeño de A y genere -1 si no hay solución.
Muestras de entrada y salida
muestra de entrada
1 5 9
muestra de salida
1 4
Código de referencia
#include <iostream>
#include <cstdio>
#include <sstream>
using namespace std;
int mp[100],sub[100],c;
int main() {
string s;
getline(cin,s);
istringstream in(s);
int t = 0;
while(in >> mp[c ++]) {
if(c > 1) {
sub[c - 2] = mp[c - 1] - mp[c - 2] - 1;
if(c % 2 == 0) t ^= sub[c - 2];
}
}
if(!t) {
printf("-1\n");
}
else {
for(int i = 0;i < c - 1;i ++) {///枚举每个人
for(int j = 1;j < mp[i + 1] - mp[i];j ++) {///移动步数
sub[i] -= j;
if(i) sub[i - 1] += j;
t = 0;
for(int k = 0;k < c - 1;k += 2) {
t ^= sub[k];
}
if(t == 0) {
printf("%d %d",mp[i],mp[i] + j);
break;
}
sub[i] += j;
if(i) sub[i - 1] -= j;
}
}
}
}