The 2019 ICPC Asia Shanghai Regional Contest 签到题

B:https://ac.nowcoder.com/acm/contest/4370/B
题意:t次查询,每次给你n个字符串,问你有没有某个串是其他更长(或者长度相等)的串的前缀。没有的话就输出Yes,若有,No。
思路:查找大量字符串的前缀,很容易想到trie。唯一需要做的就是给这些字符串按照长度排个序。不过我为了处理同一个串出现多次,用了个map来维护(大可不必,只是比赛的时候慌了而已)。至此代码也就出来了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=5e5+7;
const ll mod=1e9+7;
struct node
{
    int son[10];//纯数字串
    int  f;//我一开始以为问题在这里,就把这里改成int了
}trie[maxn];
int num=1;
void insert(string s)
{
    int len=s.length();
    int now=0;
    for(int i=0;i<len;i++)
    {
        if(trie[now].son[s[i]-'0'] )
        {
            now=trie[now].son[s[i]-'0'];
        }
        else
        {
            trie[now].son[s[i]-'0']=num++;
            now=trie[now].son[s[i]-'0'];
        }
    }
    trie[now].f++;
}
bool find(string s)
{
    int len=s.length();
    int now=0;
    for(int i=0;i<len;i++)
    {
        if(trie[now].f)
        {
            return 0;
        }
        if(trie[now].son[s[i]-'0'] )
        {
            now=trie[now].son[s[i]-'0'];
        }
        else
        {
            return 1;
        }
    }
    if(trie[now].f)
    {
        return 0;
    }
    return 1 ;
}
map<string , int > MP;//有没有都一样
ll n,m,t;
string s[10005];
vector<string > vec;
bool cmp(string a,string b)
{
    return a.length()<b.length();
}
int main()
{
    MP.clear();
    vec.clear();
    cin>>t;
    bool ans=1;
    for(int qwer=1;qwer<=t;qwer++)
    {
        ans=1;
        cin>>n;
        MP.clear();
        for(int i=0;i<n;i++)
        {
            cin>>s[i];

            MP[s[i]]++;
            if(MP[s[i]]>=2)
            {
                ans=0;
            }

        }
        sort(s,s+n,cmp);
        if(ans)
        {

            for(int i=0;i<n;i++)
            {

                if(ans)
                {
                    ans=find(s[i]);
                }
                else
                {
                    ans=0;
                    break;
                }
                insert(s[i]);
            }
        }
        cout<<"Case #"<<qwer;
        if(ans)
        {
            cout<<": Yes"<<endl;
        }
        else{
            cout<<": No"<<endl;
        }
        num=1;
        memset(trie,0,sizeof(trie));
    }
    return 0;
}

K:https://ac.nowcoder.com/acm/contest/4370/K
题意:就是给你n个点和m条边,要你对边染色,如果唯一的要求是你染色后的边如果会成环(这个环是完全由染色后的边组成的),这个环的边数不能是奇数。问你最多能涂几条边。
思路:你把这n个点分成两组,一组在左侧,另一组右侧,如果他们彼此之间会成环,如果是奇数环,那么必然某一侧存在两个点之间有一条边。那么对于这种边,不进行涂色就好。
图片说明
图片说明
上面两幅图帮助你来理解(语文好像不是一般的菜)。
再结合节点数来看一下,也就是枚举完所有情况至多图片说明 种情况。每次就来看我们需要删除多少同处于一侧的点之间的边。至此也就可以把代码写出来了。

//team yglance+xhwl+TTD
//author: CN.TTDragon
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1e5+7;
const double pi=acos(-1);
using namespace std;
int t,n,m;
vector<int > zuo,you;
ll mi=mod;
bool edge[20][20];
void check()//这个是用来计算本次需要删除多少条同侧点之间的边的。
{
    ll res=0;
//值得注意的是,两侧都要删除,可千万别只删除一侧。
    for(int i=0;i<zuo.size();i++)
    {
        for(int j=i+1;j<zuo.size();j++)
        {
            if(edge[zuo[i]][zuo[j]])
            {
                //cout<<"删除了"<<zuo[i]<<"\t"<<zuo[j]<<endl; 
                res++;
            }
        }
    }
    for(int i=0;i<you.size();i++)
    {
        for(int j=i+1;j<you.size();j++)
        {
            if(edge[you[i]][you[j]])
            {
                //cout<<"删除了"<<zuo[i]<<"\t"<<zuo[j]<<endl; 
                res++;
            }
        }
    }
    mi=min(mi,res);//取最小值,删的越少,涂的越多!
}
void dfs(int o)//大爆搜来枚举每条边在左侧还是右侧。
{
    if(o==n+1)
    {
        check();
        return ;
    }
    zuo.push_back(o);
    dfs(o+1);
    zuo.erase(zuo.end()-1);

    you.push_back(o);
    dfs(o+1);
    you.erase(you.end()-1);
}
ll u,v;
int main()
{
    ios::sync_with_stdio(false);
    //freopen("in.in","r",stdin);
    //freopen("mine.out","w",stdout);
    cin>>t;
    for(int qwe=1;qwe<=t;qwe++)
    {
        memset(edge,0,sizeof(edge));
        mi=mod;
        cin>>n>>m;
        for(int i=0;i<m;i++)
        {
            cin>>u>>v;
            edge[u][v]=1;
            edge[v][u]=1;
        }
        dfs(1);
        cout<<"Case #"<<qwe;
        cout<<": "<<m-mi<<endl;


    }
     return 0;
}

写在最后:因为队里的哥哥都去CSP了,我们就得到今年上海站的机会。三个人组队写了去年的这场比赛,队友超C,强行carry坑到爆炸的我(我trie树不排序,硬生生WA了5发)。
我必须考虑这会不会是我此生仅有的机会。
还有一个题我们队也过了(但我没参与讨论,没错我在WA),我第二天想到了假思路,WA了。就先咕一下。
CN.TTDragon加油!

全部评论

相关推荐

头像
10-09 19:35
门头沟学院 Java
洛必不可达:java的竞争激烈程度是其他任何岗位的10到20倍
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务