这道题卡了好长时间, 有必要记录一下。
可以用DFS+剪枝来遍历求解, 没到下一层就减去一部分不合理的情况, 不会超时。如下:
//我的电脑上面用不了#include <bits/stdc++.h>
//DFS的剪枝条件一定要全面 DFS全局变量最好是计数 千万不要是索引 不要过度使用
//id 一定要用 %04d 这样的形式输出
//还有0000 和 -0000 的区别 这个真有点坑
#include <cstdio>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxN=10010;
struct Node{
int first,second;
};
bool cmp(Node a, Node b){
if (a.first!=b.first) return a.first<b.first;
else return a.second<b.second;
}
vector<int> adj[maxN];
int n,m,k;
int isGirl[maxN]={0};
vector<Node> path;
int start, ed;
int first,second;
void DFS(int u, int depth){
if (depth==2){
if (u==ed || isGirl[u]!=isGirl[start]){
return;
}
first=u;
}
if (depth==3){
if (u==start || isGirl[u]!=isGirl[ed]){
return;
}
second=u;
}
if (depth==4){
if (u!=ed){
return;
}
path.push_back(Node{first, second});
return;
}
for (int i=0; i<adj[u].size(); i++){
int v=adj[u][i];
if (v!=u) DFS(v,depth+1);
}
}
int main(){
scanf("%d %d",&n,&m);
for (int i=0; i<m; i++){
string u,v;
cin>>u>>v;
int absu=abs(stoi(u));
int absv=abs(stoi(v));
adj[absu].push_back(absv);
adj[absv].push_back(absu);
if (u[0]=='-') isGirl[absu]=1;
if (v[0]=='-') isGirl[absv]=1;
}
scanf("%d",&k);
for (int i=0; i<k; i++){
scanf("%d %d",&start, &ed);
start=abs(start);
ed=abs(ed);
path.clear();
DFS(start, 1);
printf("%d\n",path.size());
sort(path.begin(), path.end(), cmp);
for (int j=0; j<path.size(); j++){
printf("%04d %04d\n",path[j].first, path[j].second);
}
}
}
还有一种更简单的方法, 因为这道题条件特殊, 只通过两个中介,所以可以找起始点的同性朋友, 终止点的同性朋友, 然后看他们两是不是朋友, 是朋友说明他们两就可以作为中介。 是不是朋友可以用一个二维数组来表示。 这种方法的思路很简单, 而且理论上说速度应该很快,但是空间会很大(通过map 映射处理的话, 空间会很小, 但是评测有16M 的空间, 怎么搞都不会用到这么大的空间)。
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxN=10010;
struct Node{
int first,second;
};
bool cmp(Node a, Node b){
if (a.first!=b.first) return a.first<b.first;
else return a.second<b.second;
}
int n,m,k;
vector<int> adj[maxN];
int rel[maxN][maxN]={0};
vector<Node> path;
int isGirl[maxN]={0};
int main(){
scanf("%d %d",&n, &m);
for (int i=0; i<m; i++){
string u,v;
cin>>u>>v;
int absU=abs(stoi(u));
int absV=abs(stoi(v));
if (u[0]=='-') isGirl[absU]=1;
if (v[0]=='-') isGirl[absV]=1;
adj[absU].push_back(absV);
adj[absV].push_back(absU);
rel[absU][absV]=rel[absV][absU]=1;
}
scanf("%d",&k);
for (int i=0; i<k; i++){
int start, ed;
scanf("%d %d",&start, &ed);
start=abs(start);
ed=abs(ed);
path.clear();
for (int j=0; j<adj[start].size(); j++){
int u=adj[start][j];
if (u!=ed && isGirl[u]==isGirl[start]){
for (int p=0; p<adj[ed].size(); p++){
int v=adj[ed][p];
if (v!=start && isGirl[v]==isGirl[ed]){
if (rel[u][v]){
path.push_back(Node{u,v});
}
}
}
}
}
sort(path.begin(), path.end(), cmp);
printf("%d\n",path.size());
for (int j=0; j<path.size(); j++){
printf("%04d %04d\n",path[j].first, path[j].second);
}
}
}
理论上说,这种解法应该很快, 但实际上最后一组数据有时候会超时。用DFS解法的话, 应该比较慢, 但实际上很快,最后一组数据一定不会超时。