Codeup墓地-2337
src:http://codeup.cn/problem.php?id=2337
2337: 阻击火箭队
时间限制: 1 Sec 内存限制: 32 MB
题目描述
小明很喜欢《神奇宝贝》(又叫做《宠物小精灵》)这部动漫,他几乎每天都要看一集神奇宝贝的动画。有一天他做了一个梦,梦见他也置身于神奇宝贝的世界,并且加入了主人公小智一行人的修行队伍。
这天,他们来到了一个由很多岛屿组成的城市。这座城市的神奇宝贝中心坐落在e岛上,里面有许多稀有的神奇宝贝。接下来正像每一集的动画那样,每次都华丽登场、悲剧收场的火箭队又出现了!
他们的目标是到e岛上抢夺神奇宝贝中心里的神奇宝贝,小明和小智他们决定阻止火箭队的行动。他们拿出该城市的地图,发现这些岛是由许多桥连接起来的。火箭队目前所在的岛是s岛,这次火箭队没有带任何高科技装备,所以他们只能从s岛走到e岛。小明和小智他们希望能找到火箭队一定会经过的桥,在那里阻止他们的行动。现在请你帮他们找出那些火箭队一定会经过的桥。
输入
输入包含多组测试数据。
每组输入的第一行为两个整数n和m(2<=n,m<=10),n表示岛的个数,m表示桥的个数。
接下来m行,每行输入两个整数a和b(0<=a,b<n),表示a岛和b岛由桥i相连接,i是桥的序号,i从0开始,按照输入的顺序依次增加1,直到m-1。
最后再输入一行,为两个整数s和e(0<=s,e<n),s表示火箭队目前所在的岛,e表示神奇宝贝中心所在的岛。
题目数据保证s岛和e岛是连通的。同时,任意两个岛之间可能会存在多个桥将它们直接相连。
相邻两组输入数据之间空一行。
输出
对于每组输入数据,找出火箭队一定会经过的桥。
每组首先在一行中输出火箭队一定会经过的桥的个数x,如果x不为0,则另起一行输出桥的序号,按照升序排序。如果x为0,则无需输出任何东西。
样例输入
3 2
0 1
1 2
0 2
6 7
1 3
0 2
2 0
4 0
1 3
1 5
0 1
2 3
样例输出
2
0 1
1
6
//按边来找两点之间所有路径的公共部分 有环 自己写的 4个小时!
#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
struct Edge{
int next,id;//next为下一个点,id为下一条边编号
Edge(int _next,int _id):next(_next),id(_id){}
};
vector<Edge>v[maxn];//邻接表
vector<int>path;//用于保存遍历过程中所走过的边编号
vector<vector<int> >paths;//用于存放所有路径
//按照路径长度升序排列cmp
bool cmp(vector<int>x,vector<int>y){return x.size()<y.size();}
void init(){//初始化函数
for(int i=0;i<maxn;i++)v[i].clear();
path.clear();
paths.clear();
}
void DFS(Edge S,int E){//S是与起点相连的{next,id},E是终点
path.push_back(S.id);
if(E==S.next){
paths.push_back(path);
path.pop_back();
return ;
}
for(int i=0;i<v[S.next].size();i++){
//如果当前路径中有这条边,则跳过
if(find(path.begin(),path.end(),v[S.next][i].id)!=path.end())continue;
DFS(v[S.next][i],E);
}
path.pop_back();//退出上一层DFS后,删掉最后一条边,返回上一层的边
}
int main(){
int n,m;//n顶点数,0~n-1, m边数,
while(~scanf("%d%d",&n,&m)){
init();
for(int i=0;i<m;i++){
int a,b;//两端点号
scanf("%d%d",&a,&b);
v[a].push_back(Edge(b,i));
v[b].push_back(Edge(a,i));
}
int s,e;
scanf("%d%d",&s,&e);
for(int i=0;i<v[s].size();i++){
Edge S(v[s][i].next,v[s][i].id);
DFS(S,e);
}
sort(paths.begin(),paths.end(),cmp);//按照路径长度升序排列
vector<int>ans;//答案路径
vector<int>vec(paths[0]);//取第一个路径(该路径是最短的)
for(int i=0;i<vec.size();i++){
bool flag=false;
int j;
for(j=1;j<paths.size();j++){
//对于第一个路径中的每条边,对所有的路径求find,如果find失败就立刻退出
if(find(paths[j].begin(),paths[j].end(),vec[i])==paths[j].end()){
flag=true;
break;
}
}
if(flag)continue;
//如果全部路径都find成功了,则将vec[i]放入ans
if(j==paths.size())ans.push_back(vec[i]);
}
//输出结果
printf("%d\n",ans.size());
if(ans.size()!=0){
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++)
printf("%d ",ans[i]);
printf("\n");
}
}
return 0;
}