21个节点 DFS搜索路径
每个点只可以访问一次 而且每条边只能访问一次 递归时改变状态 回溯时状态改回来
可能是图比较稀疏的原因 矩阵式的DFS 不加任何优化会超时 在我看来只有剪枝才可以过 边表的DFS不知道能不能过
每个点只可以访问一次 而且每条边只能访问一次 递归时改变状态 回溯时状态改回来
可能是图比较稀疏的原因 矩阵式的DFS 不加任何优化会超时 在我看来只有剪枝才可以过 边表的DFS不知道能不能过
看了下别人的思路 并查集找到能到fire的点 然后再进行回溯这样就能过了 至于大神们说的 tarjan 和 弗洛伊德算法 有兴趣的自己看吧
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 25;
int root[maxn],vis[maxn][maxn],G[maxn][maxn],point[maxn],t[maxn],fa[maxn];
int T,sum,MAX;
int findset(int x)
{
return fa[x] == x ? x: fa[x] = findset(fa[x]);
}
void Union(int x,int y)
{
int fx,fy;
fx = findset(x);
fy = findset(y);
if(fx != fy)
fa[fx] = fy;
}
void DFS(int x,int cnt)
{
if(x == T)
{
sum++;
for(int i = 0; i < cnt - 1; i++)
printf("%d ",root[i]);
printf("%d\n",root[cnt-1]);
}
for(int i = 0; i < MAX; i++)
{
if(G[x][t[i]] == 1)
{
if(vis[x][t[i]] == 0 && point[t[i]] == 0)
{
vis[x][t[i]] = vis[t[i]][x] = point[t[i]] = 1;
root[cnt] = t[i];
DFS(t[i],cnt+1);
vis[x][t[i]] = vis[t[i]][x] = point[t[i]] = 0;
}
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
int Case = 0;
while(scanf("%d",&T) != EOF)
{
printf("CASE %d:\n",++Case);
int x,y;
memset(G,0,sizeof(G));
memset(vis,0,sizeof(vis));
memset(point,0,sizeof(point));
for(int i = 0; i < maxn; i++)fa[i] = i;
MAX = 0,sum = 0;
root[0] = point[1] = 1;///标记point为1很重要 为了不产生重复的答案 /// 这里还有一个问题 如果起点只要有一个不是1 那么我的这个代码就是错的 但是只要稍微修改下就是一般化的代码了
while(scanf("%d%d",&x,&y)&& x && y)
{
Union(x,y);
G[x][y] = G[y][x] = 1;
}
for(int i = 0; i < maxn; i++)
if(findset(i) == findset(T))
t[MAX++] = i;
sort(t,t+MAX);
DFS(1,1);
printf("There are %d routes from the firestation to streetcorner %d.\n",sum,T);
}
return 0;
}