标签:
王征战回来了,为了庆祝胜利,王准备请大家吃饭!
于是n个人来到了一家豪华餐厅,这家餐厅有一张长————————长的桌子,每个人只能坐在桌子的南北两侧
一行人中,有p对A关系,m对B关系,如果u和v有A关系,则u和v必须坐在不同侧,如果u和v有B关系,则u和v必须坐在同侧
如果一种座位安排既满足所有A关系也满足所有B关系,则这种安排是和谐的。
王将会选一侧坐下,然后其他人再坐下,现在王想知道,是否存在一种和谐的座位安排。
第一行是描述中的三个整数n,p,m(2≤n≤104,0≤p≤104,0≤m≤104)
接下去n行每行一个字符串,表示参加宴会的人的名字,字符串保证不重复,不含空格且长度不超过10。
接下去p行每行两个字符串x和y,表示x和y具有A关系,x和y用空格隔开
接下去m行每行两个字符串x和y,表示x和y具有B关系,x和y用空格隔开
最后一行一个字符c,c=N表示王坐在北侧,c=S表示王坐在南侧
王的名字总是King
如果存在和谐的座位安排,则第一行输出Yes
然后接下去n行每行一个字符串s和大写英文字母c,
表示名字为s的人坐的位置,c=N表示坐在北侧,c=S表示坐在南侧
座位安排可以按任意次序输出
如果不存在这样的座位安排,输出No
Sample Input | Sample Output |
---|---|
4 3 1 King A B C A B B C A C King A N |
No |
4 3 1 King A B C A B A C King A B C N |
Yes King N A S B N C N |
解题思路:
1.将拥有 B 关系的看作连通分量(求连通分量)
2.跑A关系,保证连通分量中不存在A关系
3.连通分量缩点,进行二染色
注意到B关系我们建边后,跑连通分量可以直接用并查集维护,然后A关系我们依次检查每条边,如果拥有A关系的两个点在一个连通分量中肯定无法构造出解.
之后对连通分量跑二染色即可
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <map> #include <set> #define pb push_back /* 解题报告: 1.将拥有 B 关系的看作连通分量(求连通分量) 2.跑A关系,保证连通分量中不存在A关系 3.连通分量缩点,进行二染色 */ typedef long long ll; using namespace std; typedef pair < ll , ll > strhash; typedef pair < ll , ll > spj; map<strhash,int>new_hash; set<spj>s; const int maxn = 3e4 + 50; const ll p1 = 1526597; const ll p2 = 2807303; const ll mod1 = 1e9 + 7; const ll mod2 = 1e9 + 9; const char * kingname = "King"; inline strhash GetHashVal(const char * beg) { int len = strlen(beg); strhash res; ll x1 = 999116156; ll x2 = 1515615; for(int i = 0 ; i < len ; ++ i) { x1 = (x1 * p1 + beg[i]) % mod1; x2 = (x2 * p2 + beg[i]) % mod2; } res.first = x1 , res.second = x2; return res; } vector<int>EA[maxn] , EB[maxn] , EC[maxn]; int n,p,m,set_un[maxn],tot = 0 , colour[maxn]; char kingpos[10]; char kc,oc; char name[maxn][20]; void dfs(int cur) { set_un[cur] = tot; for(int i = 0 ; i < EB[cur].size() ; ++ i) { int nextnode = EB[cur][i]; if (set_un[nextnode] == -1) dfs(nextnode); } } bool colourmap(int cur) { for(int i = 0 ; i < EC[cur].size() ; ++ i) { int nextnode = EC[cur][i]; if (colour[cur] == colour[nextnode]) return false; if (!colour[nextnode]) { colour[nextnode] = 3 - colour[cur]; if (!colourmap(nextnode)) return false; } } return true; } int main(int argc,char *argv[]) { scanf("%d%d%d",&n,&p,&m); memset(set_un,-1,sizeof(set_un)); for(int i = 0 ; i < n ; ++ i) { scanf("%s",name[i]); strhash temp = GetHashVal(name[i]); new_hash[GetHashVal(name[i])] = i; } for(int i = 0 ; i < p ; ++ i) { char bf1[20] , bf2[20]; scanf("%s%s",bf1,bf2); int p1 = new_hash[GetHashVal(bf1)] , p2 = new_hash[GetHashVal(bf2)]; EA[p1].pb(p2) , EA[p2].pb(p1); } for(int i = 0 ; i < m ; ++ i) { char bf1[20] , bf2[20]; scanf("%s%s",bf1,bf2); int p1 = new_hash[GetHashVal(bf1)] , p2 = new_hash[GetHashVal(bf2)]; EB[p1].pb(p2) , EB[p2].pb(p1); } scanf("%s",kingpos); for(int i = 0 ; i < n ; ++ i) // 对 B 关系跑连通分量 if (set_un[i] == -1) { dfs(i); tot++; } int check = 1; for(int i = 0 ; i < n ; ++ i) { for(int j = 0 ; j < EA[i].size() ; ++ j) { int nextnode = EA[i][j]; if (set_un[i] == set_un[nextnode]) { check = 0; break; } else { int p1 = set_un[i] , p2 = set_un[nextnode]; if (p1 > p2) swap(p1,p2); spj temp(p1,p2); if (s.count(temp)) continue; EC[p1].pb(p2) , EC[p2].pb(p1) ; s.insert(temp); } } if (!check) //连通分量中存在 A 关系 { printf("No\n"); return 0; } } memset(colour,0,sizeof(colour)); for(int i = 0 ; i < tot ; ++ i) { if (!colour[i]) { colour[i] = 1; if (!colourmap(i)) { printf("No\n"); return 0; } } } printf("Yes\n"); kc = kingpos[0]; if (kc == ‘N‘) oc = ‘S‘; else oc = ‘N‘; int kingcolour = colour[set_un[new_hash[GetHashVal(kingname)]]]; for(int i = 0 ; i < n ; ++ i) { char out; if (colour[set_un[i]] == kingcolour) out = kc; else out = oc; printf("%s %c\n",name[i],out); } return 0; }
UESTC_王之盛宴 2015 UESTC Training for Graph Theory<Problem K>
标签:
原文地址:http://www.cnblogs.com/Xiper/p/4570667.html