侧边栏

2013-2014 ACM ICPC Central European Regional Contest (CERC 13) K-Digraphs

题意

要求构造一个字符方阵。给定n对字符,每对字符表示这两个字符不能出现在方阵中,输出方案

思路

很容易想到两个字符间连一条有向边,构成一张有向图,遍历它的补图,若该补图有环,则输出这个环,注意环的长度若大于20要截取;若无环,则输出最长链。
问题转化为给定一张有向图,找环,若无环,找最长链。做法是枚举起点dfs找最长链,在搜索过程中记录点的状态,当搜到点cur时,若cur到起点u有边,则找到环,此时cir记为1,便于回溯时剪枝。一开始用vector存储路径但是一直wa也搞不清问题在哪,仿照别人用的数组才过,可是看上去没差别啊

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ms(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;

const int M = int(1e5) + 5;
const int mod = int(1e9) + 7;

int g[50][50];
bool vis[30];
// vector<int> path;
// vector<int> tem;
int path[M];
int tem[M];
int plen;
bool cir;

bool dfs(int u,int cur,int len){
    vis[cur]=1;
    if(cir==1){
        return true;
    }
    if(g[cur][u]==0 && vis[u]){
        cir=1;
        // tem.push_back(cur);
        // path=tem;
        plen=len;
        path[len]=cur;
        memcpy(path,tem,sizeof(path));
        return true;
    }

    bool flag=0;
    for(int i=0;i<26;i++){
        if(g[cur][i]==0 && !vis[i]){
            flag=1;
            // tem.push_back(i);
            tem[len]=i;
            if(dfs(u,i,len+1)){
                return true;
            }
            vis[i]=0;
            // tem.pop_back();
        }
    }
    if(flag==0){
        // if(path.size()<tem.size()){
        //     path=tem;
        // }
        if(len>plen){
            memcpy(path,tem,sizeof(path));
            plen=len;
        }
    }
    return false;

}
int main(){
    int t;
    cin>>t;
    while(t--){
        // path.clear();
        // tem.clear();
        ms(path);
        ms(tem);
        cir=0;
        ms(g);
        plen=0;
        
        int n;
        cin>>n;
        while(n--){
            char a,b;
            cin>>a>>b;
            g[a-'a'][b-'a']=-1;
        }

        for(int i=0;i<26;i++){
            ms(vis);
            // tem.push_back(i);
            tem[0]=i;
            // vis[i]=1;
            // int t=0;
            // while(t<26 && g[i][t]==-1){
            //     t++;
            // }
            // if(t==26){
            //     continue;
            // }
            if(dfs(i,i,1)){
                break;
            }
            // tem.clear();
        }

        
        // int len=path.size();
        if(cir==1){
            for(int i=0;i<20;i++){
                for(int j=0;j<20;j++){
                    cout<<(char)(path[(j+i%plen)%plen]+'a');
                }
                cout<<endl;
            }
        }
        else{
            // len=max(len,39);
            int nn=plen + 1 >> 1;
            for(int i=0;i<nn;i++){
                for(int j=0;j<nn;j++){
                    cout<<(char)(path[(j+i)]+'a');
                }
                cout<<endl;
            }
        }
    }
    return 0;
}
posted @ 2020-05-18 20:32  晴人  阅读(309)  评论(0编辑  收藏  举报