zoukankan      html  css  js  c++  java
  • HDU-1181 变形课(多种方式,好题)

            首先想到的是并查集,然后WA。。。原因在这,我第一次敲的是Find(1) == Find(12)来作为可以成功的条件,实际上这样是不行的,比方说 bell 和 mail实际上是不满足条件的,可以理解为有向边,合并的时候要注意是首尾相接,可以改为Find(1) == 12 或者 Find(12) == 1,具体取决于并查集父子节点的合并关系,其次可以使用弗洛伊德算法或者DFS都可以。

    并查集:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    const int N = 26 + 5;
    int pre[N];
    
    int Find(int x){
        return pre[x] == x? x : (pre[x] = Find(pre[x]));
    }
    
    void Merge(int x, int y){
        x = Find(x), y = Find(y);
        if(x != y) pre[x] = y; //这里要注意, 如果是pre[y] = x, 则要Find(12) == 1
    }
    char ch[N*10000];
    int main(){
        while(scanf("%s", ch) == 1){
            for(int i = 0; i < 26; i++) pre[i] = i;
            while(ch[0] != '0'){
                int x = ch[0] - 'a';
                int y = ch[strlen(ch) - 1] - 'a';
                Merge(x, y);
                scanf("%s", ch);
            }
            printf("%s
    ",Find(1) == 12?"Yes.":"No.");
        }
        return 0;
    }
    弗洛伊德:
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    const int N = 26 + 5;
    const int INF = 0x3f3f3f3f;
    int mat[N][N];
    
    void Flory(){
        for(int k = 0; k < 26; k++)
            for(int i = 0; i < 26; i++)
                for(int j = 0; j < 26; j++)  mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]);
    }
    
    void Init(){
        for(int i = 0; i < 26; i++)
            for(int j = 0; j < 26; j++) mat[i][j] = (i!=j)?INF:0;
    }
    
    char ch[10010];
    int main(){
        while(scanf("%s", ch) == 1){
            Init();
            while(ch[0] != '0'){
                int x = ch[0] - 'a';
                int y = ch[strlen(ch)-1] - 'a';
                mat[x][y] = 1; //有向边
                scanf("%s", ch);
            }
            Flory();
            printf("%s.
    ",mat[1][12] < INF?"Yes":"No");
        }
        return 0;
    }
    DFS:
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    const int N = 26 + 5;
    bool dp[N][N],can;
    
    void DFS(int x){
        if(can) return ;
        if(can = (x == 12)) return ;
        for(int i=0; i < 26; i++)
            if(dp[x][i]){
                dp[x][i] = false;
                DFS(i);
                dp[x][i] = true;
            }
    }
    void Init(){
        for(int i = 0; i < 26; i++)
            for(int j = 0; j < 26; j++) dp[i][j] = false;
        can = false;
    }
    char ch[10010];
    int main(){
        while(scanf("%s", ch) == 1){
            Init();
            while(ch[0] != '0'){
                int x = ch[0] - 'a';
                int y = ch[strlen(ch)-1] - 'a';
                dp[x][y] = true;
                scanf("%s", ch);
            }
            DFS( 1 );
            printf("%s.
    ", can?"Yes":"No");
        }
    }

  • 相关阅读:
    Linux下C编程入门(1)
    Git 常用命令速查表
    Git Cheat Sheet 中文版
    Linux 在一个命令行上执行多个命令
    一个奇怪的错误的警示
    模块化编程实例(一)
    含有指针变量的结构体的指针的应用
    iOS 开发加密做法
    关于设置shadowPath的重要性
    关于设置shadowPath的重要性
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7384039.html
Copyright © 2011-2022 走看看