HDU 3829 Cat VS Dog (最大獨立點集)

這道題,要好好寫一下總結。

開始的時候,我把貓和狗作爲頂點,求最大獨立點集,但是後來發現,這個是有問題的。畫了一個圖,然後模擬了樣例2,發現這個邊可以重複,也就是說可有不同的小孩的like和dislike是一樣的,那麼這中情況下,刪除一個點,可是多少個孩子高興就不一定了。

於是感覺到這建圖是有問題的。

仔細分析一下題目,說刪除一個孩子不喜歡的動物,會使這個孩子,但是喜歡這個動物的孩子就會不高興,想讓高興的孩子儘可能的多,那麼就要刪除儘可能少的有孩子喜歡的動物,也就是說孩子和孩子之間是有衝突的,一旦孩子和孩子有衝突,對於兩個有衝突的孩子來講,只能滿足一個孩子,那麼如果兩個孩子之間沒有衝突,那麼就最多能滿足兩個孩子,那麼進一步講,如果三個孩子1, 2, 3有衝突的話,情況有兩種,第一是1討厭的是2喜歡的,也是3喜歡的,這樣的情況下2和3沒有衝突,因爲喜歡的是一樣,最多可以使得兩個孩子高興,第二是1喜歡的是2討厭也是3討厭的,那麼也就是說2和3討厭的是一樣的,喜歡不一樣也無所謂,最多讓兩個孩子高興,那如果是4個孩子呢,其實也是一樣的,滅有辦法讓四個孩子都高興。因此,如果這些孩子不衝突,那麼就可以讓每個孩子都高興!這樣的話,就是說我們可以找到最多不衝突的孩子們,注意是孩子們。爲什麼呢?或者說如何證明呢?首先我們可以確定的是相互不衝突的孩子是都可以滿足的,假設最多有m個孩子不衝突,那麼我們可以滿足m個孩子,如果我們試圖在m個孩子之外,還想讓更多的孩子高興,那麼必然要刪除動物,而這個動物必然是某一個孩子喜歡的,而另外還有至少一個孩子不喜歡的(因爲沒有衝突的孩子都別滿足了,剩下的孩子都是和其他孩子(這裏麪包括已經被滿足的孩子)有衝突的,一旦滿足了剩下的孩子中的一個,必然有至少1個孩子不被滿足,也就是說宅原來被滿足的孩子中至少有一個孩子從被滿足的狀態轉到不被滿足的狀態!因此,這道題,就是求最大獨立點集!

同時,求最大獨立點集的時候,要注意的如何建圖,有時候可以反向建圖,主要是找邊,誰和誰可以連上邊!這道題,就是將孩子作爲節點,將有衝突的孩子之間連一條邊,求最大獨立點集!

代碼:

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;

const int N = 600;
int n, m, p;
string like[N], dislike[N];
int bmap[N][N], cy[N];
bool vis[N];

bool dfs( int u )
{
    for ( int v = 1; v <= p; ++v ) if ( bmap[u][v] && !vis[v] ) {
        vis[v] = 1;
        if ( cy[v] == -1 || dfs( cy[v] ) ) {
            cy[v] = u;
            return 1;
        }
    }
    return 0;
}
int match()
{
    int res = 0; 
    memset( cy, -1, sizeof(cy) );
    for ( int i = 1; i <= p; ++i ) {
        memset( vis, 0, sizeof(vis));
        if ( dfs( i ) ) res++;
    }
    return res;
}
int main()
{
    while ( scanf("%d%d%d", &n, &m, &p) == 3 ) {
        memset( bmap, 0, sizeof(bmap));
        for ( int i = 1; i <= p; ++i ) { 
            cin >> like[i] >> dislike[i];
        }
        for ( int i = 1; i <= p; ++i ) 
            for ( int j = i+1; j <= p; ++j ) 
                if ( like[i] == dislike[j] || like[j] == dislike[i] ) bmap[i][j] = bmap[j][i] = 1;
        printf("%d\n", p-match()/2);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章