Question: given the names and nicknames of a group of people, given some relationships, what are the requirements for determining the one-to-one correspondence between names and nicknames?
Solution: At first, we directly used the owner of the hiding point and the email for edge construction, and then deleted to determine whether the result was wrong. Why? This is because we determine a possible relationship between everyone in the hiding point and the contact side of the email. However, there are also many possible relationships hidden in the question, for example, if someone is hiding in the hiding point but has not sent an email, therefore, it may be related to other unused nicknames. The correct solution is to determine the impossible relationship, because it is simpler and it is impossible for people outside the hiding point to have a relationship with emails. The initialization of an object has a relationship with all nicknames. The possible relationships are determined by excluding the Impossible relationships. Then enumerate each edge and delete it to see if the maximum match is reduced to determine whether the edge is uniquely matched. Note: If a group of name-nickname relationships are uniquely identified, only one side of the nickname is connected to the bipartite graph after all the impossible conditions are deleted.
The Code is as follows:
# Include <cstdlib> # include <cstdio> # include <cstring> # include <map> # include <set> # include <string> # include <iostream> using namespace STD; int N, idx; char G [25] [25], vis [25]; int match [25]; Map <string, int> MP, MPID; Map <int, int> mp_ret; set <int> st; set <int>: iterator it; int path (int u) {for (INT I = 1; I <= N; ++ I) {If (G [u] [I] | Vis [I]) continue; vis [I] = 1; if (! Match [I] | path (Match [I]) {match [I] = u; return 1 ;}} return 0 ;} int query () {int ret = 0; memset (match, 0, sizeof (MATCH); For (INT I = 1; I <= N; ++ I) {memset (VIS, 0, sizeof (VIS); RET + = path (I);} return ret;} void output () {Map <string, int >:: iterator it1, it2; for (it1 = MP. begin (); it1! = Mp. End (); ++ it1) {If (mp_ret.count (it1-> second) {for (it2 = MPID. Begin (); it2! = MPID. end (); ++ it2) {If (it2-> second = mp_ret [it1-> second]) {cout <it1-> first <": "<it2-> first <Endl; break ;}} else {cout <it1-> first <":??? "<Endl ;}}int main () {int t; char name [25], OP [5]; while (scanf (" % d ", & N )! = EOF) {idx = 1; MP. clear (), MPID. clear (); ST. clear (), mp_ret.clear (); memset (G, 0, sizeof (g); For (INT I = 1; I <= N; ++ I) {scanf ("% s", name); MPID [name] = I; // hash the string} while (scanf ("% s", OP ), OP [0]! = 'Q') {If (OP [0] = 'E') {// The name of the incoming person scanf ("% s", name); If (! MP. count (name) {MP [name] = idx ++;} St. insert (MP [name]);} else if (OP [0] = 'M') {// the account name scanf ("% s ", name); char in [25] = {0}; For (IT = ST. begin (); it! = ST. end (); ++ it) {// all people in the hiding place are connected to this email in [* It] = 1 ;}for (INT I = 1; I <= N; ++ I) {If (! In [I]) g [I] [MPID [name] = 1; // The person outside the email is definitely irrelevant} else if (OP [0] = 'l') {scanf ("% s", name); It = ST. find (MP [name]); ST. erase (IT) ;}} int max = query (), t; for (INT I = 1; I <= N; ++ I) {for (Int J = 1; j <= N; ++ J) {If (G [I] [J]) continue; G [I] [J] = 1; t = query (); G [I] [J] = 0; If (T <max) {mp_ret [I] = J; break ;}} output () ;}return 0 ;}