Vijos1022. Victoria的舞會(huì)2
來源:程序員人生 發(fā)布時(shí)間:2014-09-29 16:01:59 閱讀次數(shù):2813次
試題請(qǐng)參見: https://vijos.org/p/1022
題目概述
Victoria是一位頗有成就的藝術(shù)家, 他因油畫作品《我愛北京天安門》聞名于世界. 現(xiàn)在, 他為了報(bào)答幫助他的同行們, 準(zhǔn)備開一個(gè)舞會(huì).
Victoria準(zhǔn)備邀請(qǐng)n個(gè)已經(jīng)確定的人, 可是問題來了:
這n個(gè)人每一個(gè)人都有一個(gè)小花名冊(cè), 名冊(cè)里面寫著他所愿意交流的人的名字. 比如說在A的人名單里寫了B, 那么表示A愿意與B交流;但是B的名單里不見的有A, 也就是說B不見的想與A交流. 但是如果A愿意與B交流, B愿意與C交流, 那么A一定愿意與C交流. 也就是說交流有傳遞性.
Victoria覺得需要將這n個(gè)人分為m組, 要求每一組的任何一人都愿意與組內(nèi)其他人交流. 并求出一種方案以確定m的最小值是多少.
注意:自己的名單里面不會(huì)有自己的名字.
輸入
第一行一個(gè)數(shù)n. 接下來n行, 每i+1行表示編號(hào)為i的人的小花名冊(cè)名單, 名單以0結(jié)束. 1<=n<=200.
輸出
一個(gè)數(shù), m.
解題思路
赤裸裸的并查集. 我將每個(gè)人想交流的人存在一個(gè) n x n的boolean類型數(shù)組(gang)中.
不過有兩點(diǎn)需要注意:
1. 如何解決閉包的傳遞性
2. 解決有向性問題
對(duì)于每一個(gè)人(i)檢查他想交流的人(j)是否也愿意和他交流(gang[i][j] == true && gang[j][i] == true). 如果不是這樣, 需要將gang[i][j]置為false.
遇到的問題
閉包傳遞性的問題未能以較高效率解決, 因此有2個(gè)點(diǎn)超時(shí).
改進(jìn)之后可以AC.
源代碼
#include <iostream>
#include <fstream>
int main() {
using std::cin;
// std::ifstream cin;
// cin.open("input.txt");
const int SIZE = 200;
int n = 0;
bool gang[SIZE][SIZE] = {0};
int groups[SIZE] = {0};
// Initialize
for ( int i = 0; i < SIZE; ++ i ) {
groups[i] = i;
}
// Input
cin >> n;
for ( int i = 0; i < n; ++ i ) {
int person = 0;
while ( cin >> person ) {
if ( person != 0 ) {
gang[i][person - 1] = true;
} else {
break;
}
}
}
// Processing
for ( int k = 0; k < n; ++ k ) {
for ( int i = 0; i < n; ++ i ) {
for ( int j = 0; j < n; ++ j ) {
if ( gang[i][k] && gang[k][j] ) {
gang[i][j] = true;
}
}
}
}
for ( int i = 0; i < n; ++ i ) {
for ( int j = 0; j < n; ++ j ) {
if ( gang[i][j] && !gang[j][i] ) {
gang[i][j] = false;
}
}
}
for ( int i = 0; i < n; ++ i ) {
for ( int j = i + 1; j < n; ++ j ) {
if ( gang[i][j] ) {
groups[j] = groups[i];
}
}
}
// Output
int numberOfGroups = 0;
for ( int i = 0; i < n; ++ i ) {
if ( groups[i] == i ) {
++ numberOfGroups;
}
}
std::cout << numberOfGroups << std::endl;
return 0;
}
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)