題意:老師想帶他的學生們出去旅行,但是不想他們之間發生戀愛。也就是說,任意兩個可能發生戀愛的人不能同時都帶去。要求能帶去旅行的最大人數。老師認為滿足下列情況的人之間不會發生戀愛。
1.Their height differs by more than 40 cm.
2.They are of the same sex.
3.Their preferred music style is different.
4.Their favourite sport is the same (they are likely to be fans of different teams and that would result in fighting).
題解:通過Trie樹來給3,4兩個條中的字串編號。建圖是關鍵。
#include <cmath>#include <iostream>using namespace std;#define N 510bool vis[N];int bond[N][N], match[N];int cnt, mark, n;struct Student{int h, m, s;char sex;} stud[N];struct Tree { int key; Tree *next[30]; } node[N*2]; int Insert ( char* word, Tree *location ) { int i = 0, id; while ( word[i] ) { if ( word[i] != '-' ) id = word[i] - 'a';else id = 29; if ( location->next[id] == NULL ) location->next[id] = &node[++cnt]; location = location->next[id]; ++i; } if ( location->key == 0 ) location->key = ++mark; //編號 return location->key; } bool find_path ( int u ){for ( int i = 1; i <= bond[u][0]; i++ ){int v = bond[u][i];if ( ! vis[v] ){vis[v] = 1;if ( !match[v] || find_path(match[v]) ){match[v] = u;return true;}}}return false;}int Hungary (){int ans = 0;memset(match,0,sizeof(match));for ( int i = 1; i <= n; i++ ){memset(vis,0,sizeof(vis));if ( find_path(i) ) ans++;}return ans;}bool check ( int a, int b ){if ( abs(stud[a].h-stud[b].h) > 40 ) return false;if ( stud[a].sex == stud[b].sex ) return false;if ( stud[a].m != stud[b].m ) return false;if ( stud[a].s == stud[b].s ) return false;return true;}int main(){char sex;char m[110], s[110];int t, h, i, j;scanf("%d",&t);while ( t-- ){mark = 0;cnt = 2;memset(bond,0,sizeof(bond));memset(node,NULL,sizeof(node));memset(stud,0,sizeof(stud));scanf("%d",&n);for ( i = 1; i <= n; i++ ){scanf("%d %c %s %s",&h,&sex,&m,&s);stud[i].h = h;stud[i].sex = sex;stud[i].m = Insert(m,&node[0]); // node[0]做為music的根節點stud[i].s = Insert(s,&node[1]); // node[1]作為sport的根節點}for ( i = 1; i <= n; i++ ){for ( j = 1; j <= n; j++ )if ( check ( i, j ) ){bond[i][0]++;bond[i][bond[i][0]] = j;}}printf("%d\n",n-Hungary()/2);}return 0;}