思路:用vector数组存每个点的课链接点,一个数字存两点间的路段属于哪个公司
tmp是暂时存现在路线,ans是保存最优路线
vis是记录该点有没有访问过,题目说存在圈,所以用其防止重复点
dfs暴搜,如果现在路线好于历史最优路线,则ans=tmp
tmp和ans存点的时候按:点——公司——点.......——公司——点 的方式存,打印是先提取第一个,之后两个两个遍历,取公司、点,末点就是下一个始点
//还原现场,非公司vis
#include<bits/stdc++.h>
using namespace std;

const int N=1e4+10,Max=0x3f3f3f3f;

int cpy[N][N],n,m,k,a,b;
vector<int> ma[N],tmp,ans;
int mincs,minps;
int vis[N];

void dfs(int p,int ps,int c,int cs){//当前站点,当前站点sum,当前公司no,当前转公司sum
	if(p==b){
        tmp.push_back(c), tmp.push_back(p);//公司,当前站点
        if(ps<minps) ans=tmp, minps=ps, mincs=cs;
        else if(ps==minps&&cs<mincs) ans=tmp, minps=ps, mincs=cs;
        tmp.pop_back(), tmp.pop_back();
        return ;
    }
    for(auto i:ma[p]){
        if(vis[i]==0){
            if(cpy[p][i]!=c){//公司不同
                if(c!=-1) tmp.push_back(c), tmp.push_back(p);//pre公司,和下一站点(中转站)
				vis[i]=1;
                dfs(i,ps+1,cpy[p][i],cs+1);
                if(c!=-1)tmp.pop_back(), tmp.pop_back(), vis[i]=0;//还原现场
            }else{
            	vis[i]=1; 
                dfs(i,ps+1,c,cs);
                vis[i]=0;
            }    
        }
    }
}

int main(){
    
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&m,&a);
        for(int j=1;j<m;j++){
            scanf("%d",&b);
            ma[a].push_back(b), ma[b].push_back(a), cpy[a][b]=cpy[b][a]=i;
			a=b;
        }
    }
    scanf("%d",&k);
    for(int i=0;i<k;i++){
        scanf("%d%d",&a,&b);
        
        mincs=minps=Max;
		memset(vis,0,sizeof vis);
		ans.clear(), tmp.clear();
		
        vis[a]=1, tmp.push_back(a);
	
        dfs(a,1,-1,0);
        
        if(ans.size()){
    		printf("%d\n",minps-1);
            int f=*ans.begin(),e,cpyno;
            ans.erase(ans.begin());
    		while(ans.size()){
    			cpyno=*ans.begin(); ans.erase(ans.begin());
    			e=*ans.begin(); ans.erase(ans.begin());
    			printf("Go by the line of company #%d from %04d to %04d.\n",cpyno,f,e);
    			f=e;
    		}
        }else{
            puts("Sorry, no line is available.");
        }
    }
    return 0;
}

这里完整的还原现场十分重要
if(c!=-1) tmp.push_back(c), tmp.push_back(p);//pre公司,和下一站点(中转站)
vis[i]=1;
dfs(i,ps+1,cpy[p][i],cs+1);
if(c!=-1)tmp.pop_back(), tmp.pop_back(), vis[i]=0;//还原现场
这里由于第一个只给站点,没有线段不存在公司,所以先传c=-1
当时下面没有if(c!=0) 调了我两天
非公司忘记设vis