poj 2289 Jamie's Contact Groups(二分答案+网络流判定)

来源:互联网 发布:js获取当前页面html 编辑:程序博客网 时间:2024/04/28 13:28

【题目大意】:n个人,告诉你他可以从属于那些小组,现在问你将n个人分成m组,最大的组最小的人数是多少。


【解题思路】:最大最小值...想到的是二分出上界,符合条件则缩小上界,反之则增大。如何判断,可以用网络流来判定,构图是由s出发,连边到人容量为1,每个人和小组之间的对应关系连边,容量为1,小组和汇点t连边,容量为二分出来的上界...然后跑一个网络流判断汇点是否是n就可以了....


热身赛,队友不在,不会图论,硬着头皮扛,-_-!!....用的还是队友的模版......除掉模版之后...没了....


【代码】:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <string>#include <cctype>#include <map>#include <iomanip>                   using namespace std;                   #define eps 1e-8#define pi acos(-1.0)#define inf 1<<30#define linf 1LL<<60#define pb push_back#define lc(x) (x << 1)#define rc(x) (x << 1 | 1)#define lowbit(x) (x & (-x))#define ll long long#define maxn 2000#define maxm 1000000struct per{     int st[600],cnt;}per[2000];int s,t;int n,m;int dist[maxn],low[maxn],tot,eh[maxn],pre[maxn],cnt[maxn],cur[maxn];int maz[maxn][maxn],mapp[maxn][maxn]; struct Edge {    int u,v,cap,flow,next;}et[maxm]; void init() {    tot=0;    memset(eh,-1,sizeof(eh));} void add(int u,int v,int cap,int flow) {    Edge E={u,v,cap,flow,eh[u]};    et[tot]=E;    eh[u]=tot++;} void addedge(int u,int v,int cap) {    add(u,v,cap,0),add(v,u,0,0);} int isap(int s,int t,int n) {    int u,v,now;    memset(dist,0,sizeof(dist));    memset(low,0,sizeof(low));    for (u=0; u<=n; u++) cur[u]=eh[u];    int maxflow=0;    u=s;    low[s]=inf,cnt[0]=n;    while (dist[s]<n) {        for (now=cur[u]; now!=-1; now=et[now].next)            if (et[now].cap-et[now].flow && dist[u]==dist[v=et[now].v]+1) break;        if (now!=-1) {            cur[u]=pre[v]=now;            low[v]=min(low[u],et[now].cap-et[now].flow);            u=v;            if (u==t) {                for (; u!=s; u=et[pre[u]].u) {                    et[pre[u]].flow+=low[t];                    et[pre[u]^1].flow-=low[t];                }                low[s]=inf;                maxflow+=low[t];            }        }         else {            if (--cnt[dist[u]]==0) break;            dist[u]=n;            cur[u]=eh[u];            for (now=eh[u]; now!=-1; now=et[now].next)                if (et[now].cap-et[now].flow && dist[u]>dist[et[now].v]+1)                     dist[u]=dist[et[now].v]+1;             cnt[dist[u]]++;             if(u!=s) u=et[pre[u]].u;         }     }     return maxflow; }bool check(int cap) {        s=0;    t=n+m+1;    init();    for (int i=1; i<=n; i++) {        addedge(s,i,1);        for (int j=0; j<per[i].cnt; j++)            addedge(i,per[i].st[j]+n+1,1);    }    for (int i=1; i<=m; i++) addedge(i+n,t,cap);    if (isap(s,t,t-s+1)==n) return true;    else return false;} int main(){    char ch;    string name;    while(~scanf("%d%d",&n,&m)){        if (n==0 && m==0) break;        for (int i=1; i<=n; i++) {            cin >> name;            per[i].cnt=0;            ch=getchar();            while (ch!='\n'){                scanf("%d",&per[i].st[per[i].cnt]);                per[i].cnt++;                ch=getchar();            }        }        int l=1,r=n,ans=-1;        while (l<=r) {            int mid=(l+r)/2;            if (check(mid)) {                ans=mid;                r=mid-1;            }            else l=mid+1;        }        printf("%d\n",ans);    }    return 0;}  


原创粉丝点击