poj1486(二分图删边匹配)

来源:互联网 发布:软件管家官网 编辑:程序博客网 时间:2024/05/21 19:23

题意:给n(n<=26)张幻灯片,每张上面都有一个数字。给出所有幻灯片的位置和数字的位置,问哪些幻灯片上的数字可以确定。


解法:首先,如果给的合法的话,匈牙利算出来的一定是完全匹配的(也就是说,第一遍二分匹配算出来的一定是完全匹配)。然后再尝试删掉每一条完全匹配中的边,如果删掉后不能完全匹配,则说明这条边是必须的,所以就确定了这个匹配并输出。如果算出的完全匹配中没有一个匹配是必须的,就输出none好了。


代码:

/******************************************************* author:xiefubao*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <string.h>//freopen ("in.txt" , "r" , stdin);using namespace std;#define eps 1e-8const double pi=acos(-1.0);typedef long long LL;const int Max=10100;const int INF=1000000007;int n;struct rec{    int minx,miny,maxx,maxy;} recs[30];bool num[30][30];bool used[30];int match[30];int match2[30];struct point{    int x,y;} points[30];bool OK(const rec& re,const point& p){    return (p.x>=re.minx&&p.x<=re.maxx&&p.y>=re.miny&&p.y<=re.maxy);}bool dfs(int k){     for(int i=0;i<n;i++)     {         if(used[i]||!num[i][k]) continue;         used[i]=1;         if(match[i]==-1||dfs(match[i]))         {            match[i]=k;            return 1;         }     }     return 0;}bool dfs2(int k){     for(int i=0;i<n;i++)     {         if(used[i]||!num[i][k]) continue;         used[i]=1;         if(match2[i]==-1||dfs(match2[i]))         {            match2[i]=k;            return 1;         }     }     return 0;}bool make(){    int tool=0;    memset(match,-1,sizeof match);    for(int i=0;i<n;i++)    {         memset(used,0,sizeof used);            if(dfs(i)) tool++;            else break;    }    return tool==n;}void solve(){    bool flag=1;    for(int i=0;i<n;i++)    {        num[i][match2[i]]=0;        if(!make())        {            if(!flag) printf(" ");            printf("(%c,%d)",'A'+i,match2[i]+1);            flag=0;        }        else continue;        num[i][match2[i]]=1;    }    if(flag)   printf("none\n");   else printf("\n");}int main(){    int kk=1;    while(scanf("%d",&n)==1)    {        memset(num,0,sizeof num);        if(n==0)            break;        for(int i=0; i<n; i++)            scanf("%d%d%d%d",&recs[i].minx,&recs[i].maxx,&recs[i].miny,&recs[i].maxy);        for(int i=0; i<n; i++)            scanf("%d%d",&points[i].x,&points[i].y);        for(int i=0; i<n; i++)            for(int j=0; j<n; j++)                num[i][j]=OK(recs[i],points[j]);        memset(match,-1,sizeof match);        int tool=0;        printf("Heap %d\n",kk++);        for(int i=0;i<n;i++)        {            memset(used,0,sizeof used);            if(dfs(i)) tool++;        }        for(int i=0;i<n;i++)            match2[i]=match[i];        solve();        puts("");    }    return 0;}

0 0
原创粉丝点击