AtCoder Beginner Contest 287 C-E

C - Path Graph?

样例

题意:就是看给的点和边能不能形成一条路径(就一条线,没有多余的东西)

思路一:这个题我觉得就是一个大模拟,题意就表明了就是所有点连成一条线,就照着这个思路模拟出来就行,从起点出发向后走看看能不能到达终点即可(这个模拟的实质也是bfs)

前提条件:正好有(n−1)条边每个顶点的度数必须最多2,图形已连接。

代码

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,m;
    cin>>n>>m;
    vector<vector<int> >g(n);
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        u-=1,v-=1;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    if(m!=n-1){
        cout<<"No"<<endl;
        return 0;
    }
    for(int i=0;i<n;i++){
        if(g[i].size()>2){
            cout<<"No"<<endl;
            return 0;
        }
    }
    
    vector<bool> reach(n);  
    queue<int> q;
    reach[0]=true;  //起点从1即0开始
    q.push(0);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=0;i<g[u].size();i++){
            if(!reach[g[u][i]]){
                reach[g[u][i]]=true;
                q.push(g[u][i]);
            }
        }
    }
    for(int i=0;i<n;i++){
        if(!reach[i]){
            cout<<"No"<<endl;
            return 0;
        }
    }
    cout<<"Yes"<<endl;
    return 0;
}

思路二:并查集(板题)

#include <bits/stdc++.h>
using namespace std;
 
int v[200000+5];
 
int find(int x){
    if(v[x]==x)
        return x;
    v[x]=find(v[x]);
    return v[x];
}
 
int main()
{
    ios::sync_with_stdio(false); 
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin>>n>>m; 
    for(int i=1;i<=n;i++)  v[i]=i;
    for(int i=0;i<m;i++){
        int u,t;
        cin>>u>>t;
        int t1=find(max(u,t)),t2=find(min(u,t));
        v[t1]=v[t2];
    }
    if (m!=n-1){
        cout<<"No";
        return 0;
    }
    for(int i=1;i<=n;i++){
        v[i]=find(i);
    }
    int flag=1;
    for(int i=1;i<=n;i++){
        if(i!=1 && v[i]!=v[1]){
            flag=0;
            break;
        }
    }
    if(flag)   cout<<"Yes";
    else   cout<<"No";
}

D - Match or Not

题意:给了两个字符串,第二个字符串比第一个字符串少一个字符,第一个字符串从第一个位置到最后依次删去每个位置上的字符使其与第二个字符长度一致,看看第一个字符串的每个子字符串是否与第二个字符串相同,其中两个字符串的‘?’可以任意修改为其他的字符。

思路:就是前后找相同的长度位置,每次检索一个点检查该位置前后是否能与第二个字符串相同。

代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s,t;
    cin>>s>>t;
    vector<int> pre(s.size()+1,false),suf(s.size()+1,false);  //前后相同的长度  
    pre[0]=true,suf[0]=true;
     
    for(int i=0;i<t.size();i++){
        if(s[i]==t[i] || s[i]=='?' || t[i]=='?')  pre[i+1]=true;
        else    break;
    }
    
    reverse(s.begin(),s.end());
    reverse(t.begin(),t.end());
    for(int i=0;i<t.size();i++){
        if(s[i]==t[i] || s[i]=='?' || t[i]=='?')  suf[i+1]=true;
        else    break;
    }    
    
    for(int i=0;i<=t.size();i++){
        if(pre[i] && suf[t.size()-i])    cout<<"Yes\n";
        else    cout<<"No\n";
    }
}

E - Karuta

题意:给了一个字符串数组,求每个字符串与其他字符串的最大前缀长度

思路:字典树板子题

代码:

#include <bits/stdc++.h>
using namespace std;

const int N=5e5+5;
int son[N][26],cnt[N],idx;
char str[N];
string s[N];

void insert(const char *str,int v){
    int p=0;
    for(int i=0;str[i]!='\0';i++){
        cnt[p]+=v;
        int u=str[i]-'a';
        if(!son[p][u])    son[p][u]= ++idx;
        p=son[p][u];
    }
    cnt[p]+=v;
}

int query(const char *str){
    int p=0,ans=0;
    for(int i=0;str[i]!='\0';i++){
        int u=str[i]-'a';
        if(!son[p][u])    return ans;
        p=son[p][u];
        if(cnt[p]==0)    return ans;
        ++ans;
    }
    return ans;
}

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        insert(s[i].c_str(),1);
    }
    for(int i=1;i<=n;i++){
        insert(s[i].c_str(),-1);
        cout<<query(s[i].c_str())<<endl;
        insert(s[i].c_str(),1);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值