题解 P1407 【[国家集训队]稳定婚姻】

Baihua

2019-01-22 16:45:07

Solution

#### 这里介绍一种二分图匹配做法。 * 考虑题目所描述的过程,我们应该 **先拆散一对夫妻**,然后试图为被拆散的男方匹配。 * 题目所给出的夫妻在没有被拆散的的情况下,一定是一对一的,因此如果匹配成功,那么在 ** 匈牙利算法的最后阶段,那个没有被匹配的点一定是先前被拆散的 ** * 因此我们模拟这个过程 : 1.拆散一对夫妇 2.试图重新匹配 3.如果匹配成功,那么他们就是不安全的 * 注意事项: 数组开到足够用的 * 下面是代码: ``` #include <iostream> #include <fstream> #include <algorithm> #include <math.h> #include <stdio.h> #include <cstring> #include <map> #define re register #define GC getchar() #define Clean(X,K) memset(X,K,sizeof(X)) using namespace std ; int Qread () { int X = 0 ,F = 1; char C = GC ; while (C > '9' || C < '0') { if (C == '-') F = -1 ; C = GC ; } while (C >='0' && C <= '9') { X = X * 10 + C - '0' ; C = GC ; } return X *F ; } /* 头文件和准备工作 */ const int Maxn = 8005 , Maxm = 20005 ; int Men[Maxn] , Cnt = 0 , Low[Maxn] , Dfn[Maxn] , Vis[Maxn] , En = 0 , Head[Maxn] , N , M , Match[Maxn] , S[Maxn] , T = 0; struct Edge { int Fr , Gt , Nxt ; }; Edge E[Maxm * 2] ; void Adg (int X , int Y) { ++ En ; E[En].Fr = X ; E[En].Gt = Y ; E[En].Nxt = Head[X] ; Head[X] = En ; } map <string , int > A ; bool DFS (int X) { for (re int i = Head[X] ; i; i = E[i].Nxt ) { if (Vis[E[i].Gt]) continue ; Vis[E[i].Gt] = 1 ; if (Match[E[i].Gt] == 0 || DFS (Match[E[i].Gt])) { return true ; } } return false ; } int main () { //freopen ("P1407.in" , "r" , stdin) ; Clean (Head , 0) , Clean (Match , 0), Clean (Low , 0) , Clean (Dfn , 0) , Clean(Vis , 0) ; N = Qread () ; for (re int i = 1 ; i <= N; ++ i) { string S1 , S2 ; cin >> S1 >> S2 ; int X , Y ; if (A[S1]) X = A[S1] ; else A[S1] = X = ++ Cnt ; if (A[S2]) Y = A[S2] ; else A[S2] = Y = ++ Cnt ; Match[Y] = X , Match[X] = Y ; Men[X] =1 , Men[Y] = 0 ; } M = Qread () ; for (re int i = 1 ; i <= M ; ++ i) { string S1 , S2 ; cin >> S1 >> S2 ; int X = A[S1] , Y = A[S2] ; Adg (X , Y) ; } /* 建立图 */ for (re int i = 1 ; i <= Cnt ; ++ i) if (Men[i]) { Clean (Vis , 0) ; Match[Match[i]] = 0 ; //拆散一对夫妇 if (DFS (i)) printf ("Unsafe\n") ; else printf ("Safe\n") ; Match[Match[i]] = i ; //让他们重新连接,方便以后的操作。 } fclose (stdin) ; fclose (stdout); return 0; } ``` #### Thanks!