poj 1486 Sorting Slides(二分图匹配)

来源:互联网 发布:retrofit源码分析 编辑:程序博客网 时间:2024/06/05 18:36

真是不看题解,怎么也搞不清楚题目要求什么。。先说建边还是比较好建的,判断点是否在幻灯片的范围内,在就连一条边。一直以为必须要每个页码都能匹配上幻灯片,随便匹配,只要能给页码分配个幻灯片就行,才能输出结果呢。直到wa到怀疑人生,搜了下题解,原来只要有某个页码能完全确定匹配上某一页幻灯片,输出就行了。
因为页码本来就在幻灯片上,所以最大匹配肯定是就是幻灯片个数,即完美匹配。
先求出最大匹配,判断最大匹配是不是完美匹配,不是的话,就none了,是的话,就挨个删边,删掉每个边后,再跑一遍最大匹配,如果最大匹配不变,那么那条边就是不确定的。如果最大匹配变小了,就说明那条边是唯一确定的,输出就行了。

#include <stdio.h>#include <string.h>#include <set>#include <utility>using namespace std;const int MAXN = 30;int uN,vN;//u,v的数目,使用前面必须赋值int g[MAXN][MAXN];//邻接矩阵int linker[MAXN];int path[MAXN];bool used[MAXN];bool dfs(int u){    for(int v = 0; v < vN; v++)        if(g[u][v] && !used[v])        {            used[v] = true;            if(linker[v] == -1 || dfs(linker[v]))            {                linker[v] = u;                return true;            }        }    return false;}int hungary(){    int res = 0;    memset(linker,-1,sizeof(linker));    for(int u = 0; u < uN; u++)    {        memset(used,false,sizeof(used));        if(dfs(u))res++;    }    return res;}struct PPT{    int xmin,xmax,ymin,ymax,id;    bool operator==(const PPT& b) const    {        return xmin == b.xmin && xmax == b.xmax && ymin == b.ymin && ymax == b.ymax;    }    bool contain(int x, int y)    {        return x >= xmin && x <= xmax && y >= ymin && y <= ymax;    }} ppt[MAXN];int main(){    int n,x,y,cnt = 0;    while(scanf("%d",&n) && n)    {        ++cnt;        uN = vN = n;        memset(g,0,sizeof(g));        for(int i = 0; i < n; ++i)        {            scanf("%d %d %d %d",&ppt[i].xmin,&ppt[i].xmax,&ppt[i].ymin,&ppt[i].ymax);            ppt[i].id = i;        }        for(int i = 0; i < n; ++i)        {            scanf("%d %d",&x,&y);            for(int j = 0; j < n; ++j)            {                if(ppt[j].contain(x,y))                    g[i][ppt[j].id] = 1;            }        }        printf("Heap %d\n",cnt);        int res = hungary();        if(res != n)        {            printf("none\n\n");            continue;        }        bool flag = true;        for(int i = 0; i < n; ++i) path[i] = linker[i];        for(int i = 0; i < n; ++i)        {            if(path[i] == -1) continue;            g[path[i]][i] = 0;            int t = linker[i];            res = hungary();            g[path[i]][i] = 1;            if(res != n)            {                printf("(%c,%d) ",i+'A',path[i]+1);                flag = false;            }        }        if(flag)        {            printf("none\n\n");            continue;        }        printf("\n\n");    }    return 0;}
阅读全文
0 0
原创粉丝点击