2017BAPC初赛A(思维,无序图,向量)

#include<bits/stdc++.h>
using namespace std;
string goods,sister[100010];
int x,m;
unordered_map<string,int>mp;
vector<int>g[100010],great,les;
int road()
{
    great.push_back(1);
    les.push_back(1);
    int shopping=0;//正序从商店开始浏览
    for(int i=1;i<=m;i++)
    {
        vector<int>&tmp=g[mp[sister[i]]];//列举包含该商品的所有商店
        int pos=lower_bound(tmp.begin(),tmp.end(),shopping)-tmp.begin();//找到第一次出现该商品的商店位置
        if(pos>=(int)tmp.size())//该商品在未访问的商店没有的卖
            return 0;
        shopping=tmp[pos];//出现该商品的商店,每次移动到这位置
        great.push_back(shopping);//添加进入正序商店路线
    }
    int rshopping=*g[mp[sister[m]]].rbegin();//找到最后一件购买的商品有卖的最远的商店
    for(int i=m;i>=1;i--)
    {
        vector<int>&tmp=g[mp[sister[i]]];
        int pos=upper_bound(tmp.begin(),tmp.end(),rshopping)-tmp.begin()-1;//尽可能选择高的路径(在一家商店连续购买【反序购买】),如果和原本路径一致则答案唯一
        rshopping=tmp[pos];
        les.push_back(rshopping);
    }
    for(int i=1;i<=m;i++)
        if(great[i]!=les[m-i+1])//路线不一致
            return 2;
    return 1;
}
int main()
{
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int k;
    cin>>k;
    int cnt=1;
    for(int i=1;i<=k;i++)
    {
        cin>>x>>goods;
        if(!mp.count(goods))//如果这个商品第一次出现
            mp[goods]=cnt++;//给它一个编号
        g[mp[goods]].push_back(x);//将这个商店的位置放入商品编号的向量中
    }
    for(int i=1;i<cnt;i++)
        sort(g[i].begin(),g[i].end(),less<int>());//升序排序,和正常访问商店顺序一致
    cin>>m;
    int flag=0;
    for(int i=1;i<=m;i++)
    {
        cin>>sister[i];
        if(!mp.count(sister[i]))//商店里没有列表商品
            flag=1;
    }
    if(flag==1||road()==0)
        printf("impossible");
    else if(road()==1)
        printf("unique");
    else
        printf("ambiguous");
    return 0;
}

/*less<int>升序排列,不写默认升序,greater<int>降序排列,不写就排反了,lower_bound大于等于的第一个地址,upper_bound严格大于的第一个地址,如果用begin()和end()会返回迭代器(我也不知道迭代器是啥)数组的话可以直接+下标,查询区间是左闭右开区间*/

posted @ 2018-08-25 10:00  sewage  阅读(172)  评论(0编辑  收藏  举报