【思维】欧拉路+建模——uva10129

建模型的思路值得学习

最原始的思路:直接把单词看成一个点,然后和前后可相连的进行连边,但是本题这样做复杂度太大了

不如将单词抽象成一条边,a-z总共26个字符抽象成点,由单词首字母连向单词尾字母

本题就变成了在图上跑欧拉通路

 

建完图后只要判一判这个图是不是欧拉图就行,1.考虑是否至多有两个点的度数为奇数,2.考虑是否联通

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int in[100],out[100],mp[50][50];
char s[N];

int vis[N]; 
void dfs(int u){
    vis[u]=1;
    for(int i=0;i<26;i++)
        if(mp[u][i] && !vis[i])dfs(i);
}

int main(){
    int n,t;cin>>t;
    while(t--){
        cin>>n;
        memset(in,0,sizeof in);
        memset(out,0,sizeof out); 
        memset(mp,0,sizeof mp);
        memset(vis,0,sizeof vis);
        
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            int len=strlen(s);
            out[s[0]-'a']++;
            in[s[len-1]-'a']++;
            mp[s[0]-'a'][s[len-1]-'a']++;
        }
        
        int p=-1,f1=0,f2=0;
        for(int i=0;i<26;i++){
            if(in[i]==out[i])continue;
            else if(in[i]+1==out[i])f2++,p=i;
            else if(in[i]==out[i]+1)f1++;
            else f1=-0x3f3f3f3f;
        }
        if(f1<0 || f1>1 || f2>1){
            cout<<"The door cannot be opened."<<'\n';
            continue;
        }
        //判联通性
        if(p>=0)dfs(p);//欧拉通路 
        else { //欧拉回路 
            for(int i=0;i<26;i++)
                if(in[i]){
                    dfs(i);break;
                }
        } 
        int f=0;
        for(int i=0;i<26;i++)
            if((in[i] || out[i]) && vis[i]==0)f=1;
        if(f) cout<<"The door cannot be opened."<<'\n';
        else cout<<"Ordering is possible."<<'\n';
    }
} 

 

posted on 2020-05-25 14:12  zsben  阅读(152)  评论(0编辑  收藏  举报

导航