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();//找到最後一件購買的商品
vector<int>&tmp=g[mp[sister[m]]];
int pos=tmp.end()-tmp.begin()-1;//盡可能從後序的商店出發買商品,盡可能制造和上面路線之間的差異
rshopping=tmp[pos];
les.push_back(rshopping);
for(int i=m-1;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()會返回叠代器(我也不知道叠代器是啥)數組的話可以直接+下標,查詢區間是左閉右開區間*/
2017BAPC初賽A(思維,無序圖,向量)