hihocoder1393(二分图多重匹配)

来源:互联网 发布:德云社 知乎 编辑:程序博客网 时间:2024/06/06 22:24

题目

是一个裸地二分图多重匹配,但是做法十分粗糙,强行遍历了0-500,如果是普通的方法会TLE,用了ISAP实现。晚一些改一下。
感觉多重匹配和最大匹配的差别在于一个点能否使用多次。也就是边权是否为1。(但是感觉有什么地方不大对)

#include<bits/stdc++.h>using namespace std;const int MAXN = 100010;//点数的最大值const int MAXM = 400010;//边数的最大值const int INF = 0x3f3f3f3f;struct Edge{    int to,next,cap,flow;} edge[MAXM]; //注意是MAXMint tol;int head[MAXN];int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN],n,m;void init(){    tol = 0;    memset(head,-1,sizeof(head));}//加边,单向图三个参数,双向图四个参数void addedge(int u,int v,int w,int rw=0){    edge[tol].to = v;    edge[tol].cap = w;    edge[tol].next = head[u];    edge[tol].flow = 0;    head[u] = tol++;    edge[tol].to = u;    edge[tol].cap = rw;    edge[tol].next = head[v];    edge[tol].flow = 0;    head[v]=tol++;}//输入参数:起点、终点、点的总数//点的编号没有影响,只要输入点的总数int sap(int start,int end,int N){    memset(gap,0,sizeof(gap));    memset(dep,0,sizeof(dep));    memcpy(cur,head,sizeof(head));    int u = start;    pre[u] = -1;    gap[0] = N;    int ans = 0;    while(dep[start] < N)    {        if(u == end)        {            int Min = INF;            for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])                if(Min > edge[i].cap - edge[i].flow)                    Min = edge[i].cap - edge[i].flow;            for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])            {                edge[i].flow += Min;                edge[i^1].flow -= Min;            }            u = start;            ans += Min;            continue;        }        bool flag = false;        int v;        for(int i = cur[u]; i != -1; i = edge[i].next)        {            v = edge[i].to;            if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])            {                flag = true;                cur[u] = pre[v] = i;                break;            }        }        if(flag)        {            u = v;            continue;        }        int Min = N;        for(int i = head[u]; i != -1; i = edge[i].next)            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)            {                Min = dep[edge[i].to];                cur[u] = i;            }        gap[dep[u]]--;        if(!gap[dep[u]])return ans;        dep[u] = Min+1;        gap[dep[u]]++;        if(u != start) u = edge[pre[u]^1].to;    }    return ans;}int main(){    int t,sum,temp;    scanf("%d",&t);    while (t--)    {        sum=0;        init();        scanf("%d %d",&n,&m);        for (int i = 1; i <= m; i++)        {            scanf("%d",&temp);            addedge(i+100,500,temp);            sum += temp;        }        for(int i = 1; i <= n; i++)        {            int t1,t2;            scanf("%d %d",&t1,&t2);            addedge(0,i,t1);            for(int j =0; j < t2; j++)            {                scanf("%d",&temp);                addedge(i,temp+100,1);            }        }        if (sum == sap(0,500,500))            printf("Yes\n");        else printf("No\n");    }    return 0;}
原创粉丝点击