UVALive 6590 Digraphs (DFS找环找通路)

33 篇文章 0 订阅

大体题意:

给你n个字符串(长度为2),表示这些字符串不准出现在矩阵中,让你构造一个尽可能大的字符矩阵,如果大小超过了20×20,那么就输出20×20的即可,否则输出你构造的矩阵?

吐槽:

真是服气了,忘记了回溯,改了一晚上= =!(好弱)

思路:

字符串的长度始终是2,很明显是一个图的题目,且出现的字符串是禁止使用的,因此我们可以给g[][]数组初始化-1,输入一个变成0即可!

然后在剩下的图中,如果存在有向环的话,肯定是可以无限输出的!

否则就找出一条最长的通路,长度为lenp,那么矩阵的大小边 就是  (lenp + 1 )/2.

上述结论分析以下便知!

然后既是dfs了,记得回溯vis数组即可!

大体说下dfs写法:

枚举起点,判断是否能以起点开始找到以起点结束的环,如果能直接return 1了,否则就找出最大通路 return 0!

详细见代码:

注意:

memcpy  中sizeof 是第一个数组的,否则内存溢出!

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 30;
char cmd[maxn];
int vis[maxn];
int g[maxn][maxn];
int path[maxn<<5];
int ans[maxn<<2];
int lenp;
bool circle = 0;
int dfs(int u,int cur,int s){
    if (circle)return 1;
    vis[u] = 1;
    bool ok = 0;
    if (g[u][s] && vis[s]){
        path[cur] = u;
        lenp = cur;
		circle = 1;
        memcpy(ans,path,sizeof ans);
        return 1;
    }
    for (int i = 0; i < 26; ++i){
        if (g[u][i] && !vis[i]){
            ok = 1;
            path[cur] = i;
            if (dfs(i,cur+1,s))return 1;
            vis[i] = 0;
        }
    }
    if (!ok){
        if (cur > lenp){
            memcpy(ans,path,sizeof ans);
            lenp = cur;
        }   
    }
    return false;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        circle = 0;
        scanf("%d",&n);
        lenp = 0;
        memset(g,-1,sizeof g);
        for (int i = 0; i < n; ++i){
            scanf("%s",cmd);
            g[cmd[0]-'a'][cmd[1]-'a'] = 0;
        }
        for (int i = 0; i < 26; ++i){
            memset(vis,0,sizeof vis);
            path[0] = i;
            if (dfs(i,1,i))break;
        }
        if (circle){
            for (int i = 0; i < 20; ++i){
                int s = i % lenp;
                for (int j = 0; j < 20; ++j){
                    printf("%c",ans[(s+j)%lenp] + 'a');
                }
                puts("");
            }

        }
        else {
            int n = lenp + 1 >> 1;
            for (int i = 0; i < n; ++i){
                int s = i;
                for (int j = 0; j < n; ++j){
                    printf("%c",ans[s+j] + 'a');
                }
                puts("");
            }
        }
    }


    return 0;
}
/**
100
3
ab
bc
ca
4
ab
bc
cd
ad
5
ab
bc
ca
cd
ad
**/



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值