HDU 3277 Marriage Match III(拆點+二分+最大流SAP)

來源:互聯網
上載者:User

標籤:des   style   blog   color   java   os   io   strong   

這個題目是說,有n個女的和男的找伴侶。然後女的具有主動選擇權,每個女的可以選自己喜歡的男的,也可以挑選k個不喜歡的男的,做法就是:把女的拆點,u1->u2建立一條容量為k的邊。如果遇見喜歡的男生i->j+2*n建一條容量為1的邊,否則i+n->j+2*n建一條容量為1的邊。最後將源點和女生相連容量為mid,匯點與男生相連容量為mid。枚舉mid,看是否會產生滿流。

可能姿勢不夠優美dinic逾時了啊,換成SAP快了很多啊、、、

Marriage Match IIITime Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1405    Accepted Submission(s): 421


Problem DescriptionPresumably, you all have known the question of stable marriage match. A girl will choose a boy; it is similar as the ever game of play-house . What a happy time as so many friends play together. And it is normal that a fight or a quarrel breaks out, but we will still play together after that, because we are kids. 

Now, there are 2n kids, n boys numbered from 1 to n, and n girls numbered from 1 to n. As you know, ladies first. So, every girl can choose a boy first, with whom she has not quarreled, to make up a family. Besides, the girl X can also choose boy Z to be her boyfriend when her friend, girl Y has not quarreled with him. Furthermore, the friendship is mutual, which means a and c are friends provided that a and b are friends and b and c are friend. 

Once every girl finds their boyfriends they will start a new round of this game—marriage match. At the end of each round, every girl will start to find a new boyfriend, who she has not chosen before. So the game goes on and on. On the other hand, in order to play more times of marriage match, every girl can accept any K boys. If a girl chooses a boy, the boy must accept her unconditionally whether they had quarreled before or not. 

Now, here is the question for you, how many rounds can these 2n kids totally play this game?
 
InputThere are several test cases. First is an integer T, means the number of test cases. 
Each test case starts with three integer n, m, K and f in a line (3<=n<=250, 0<m<n*n, 0<=f<n). n means there are 2*n children, n girls(number from 1 to n) and n boys(number from 1 to n).
Then m lines follow. Each line contains two numbers a and b, means girl a and boy b had never quarreled with each other. 
Then f lines follow. Each line contains two numbers c and d, means girl c and girl d are good friends.
 
OutputFor each case, output a number in one line. The maximal number of Marriage Match the children can play. 
Sample Input
14 5 1 21 12 33 24 24 41 42 3
 
Sample Output
3
 
#include <algorithm>#include <iostream>#include <stdlib.h>#include <string.h>#include <iomanip>#include <stdio.h>#include <string>#include <queue>#include <cmath>#include <stack>#include <map>#include <set>#define eps 1e-12///#define M 1000100#define LL __int64///#define LL long long///#define INF 0x7ffffff#define INF 0x3ffffff#define PI 3.1415926535898#define zero(x) ((fabs(x)<eps)?0:x)using namespace std;const int maxn = 1010;///int deep[maxn];int cnt;int n, m, k;int S, T;int fa[maxn];int vis[maxn][maxn];int cur[maxn], head[maxn];int dis[maxn], gap[maxn];int aug[maxn], pre[maxn];struct node{    int v, w;    int next;} f[510000];struct node1{    int l, r;} pp[50010];int Find(int x){    if(x != fa[x]) fa[x] = Find(fa[x]);    return fa[x];}void Union(int x,int y){    int xx,yy;    xx=Find(x);    yy=Find(y);    if(xx!=yy)        fa[xx]=yy;}void init(){    cnt = 0;    memset(head, -1, sizeof(head));    for(int i = 1; i <= n; i++) fa[i] = i;}void add(int u, int v, int w){    f[cnt].v = v;    f[cnt].w = w;    f[cnt].next = head[u];    head[u] = cnt++;    f[cnt].v = u;    f[cnt].w = 0;    f[cnt].next = head[v];    head[v] = cnt++;}int SAP(int s, int e, int n){    int max_flow = 0, v, u = s;    int id, mindis;    aug[s] = INF;    pre[s] = -1;    memset(dis, 0, sizeof(dis));    memset(gap, 0, sizeof(gap));    gap[0] = n;    for (int i = 0; i <= n; ++i)  cur[i] = head[i];/// 初始化當前弧為第一條弧    while (dis[s] < n)    {        bool flag = false;        if (u == e)        {            max_flow += aug[e];            for (v = pre[e]; v != -1; v = pre[v]) /// 路徑回溯更新殘留網路            {                id = cur[v];                f[id].w -= aug[e];                f[id^1].w += aug[e];                aug[v] -= aug[e]; /// 修改可增廣量,以後會用到                if (f[id].w == 0) u = v; /// 不回退到源點,僅回退到容量為0的弧的弧尾            }        }        for (id = cur[u]; id != -1; id = f[id].next)/// 從當前弧開始尋找允許弧        {            v = f[id].v;            if (f[id].w > 0 && dis[u] == dis[v] + 1) /// 找到允許弧            {                flag = true;                pre[v] = u;                cur[u] = id;                aug[v] = min(aug[u], f[id].w);                u = v;                break;            }        }        if (flag == false)        {            if (--gap[dis[u]] == 0) break; ///gap最佳化,層次樹出現斷層則結束演算法            mindis = n;            cur[u] = head[u];            for (id = head[u]; id != -1; id = f[id].next)            {                v = f[id].v;                if (f[id].w > 0 && dis[v] < mindis)                {                    mindis = dis[v];                    cur[u] = id; /// 修改標號的同時修改當前弧                }            }            dis[u] = mindis + 1;            gap[dis[u]]++;            if (u != s) u = pre[u]; /// 回溯繼續尋找允許弧        }    }    return max_flow;}void build(int mid){    int a, b;    cnt = 0;    memset(head, -1, sizeof(head));    S = 0;    T = 3*n+1;    for(int i = 1 ; i <= n; i++)    {        add(S, i, mid);          add(i+2*n, T, mid);        add(i, i+n, k);    }    memset(vis, 0, sizeof(vis));    for(int i = 0; i < m; i++)    {        a = pp[i].l;        b = pp[i].r;        vis[Find(a)][b] = 1;    }    for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= n; j++)        {            if(!vis[Find(i)][j]) add(i+n, j+2*n, 1);            else add(i, j+2*n, 1);        }    }}int main(){    int K;    cin >>K;    while(K--)    {        int p;        scanf("%d %d %d %d",&n, &m, &k, &p);        init();        for(int i = 0; i < m; i++) scanf("%d %d",&pp[i].l, &pp[i].r);        int x, y;        while(p--)        {            scanf("%d %d",&x, &y);            Union(x, y);        }        int l = 0;        int r = n;        int ans = 0;        int mid;        while(l <= r)        {            mid = (l+r)>>1;            build(mid);            if(SAP(0, 3*n+1, 3*n+2) >= n*mid)            {                l = mid+1;                ans = mid;                continue;            }            r = mid-1;        }        printf("%d\n",ans);    }    return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.