• POJ 1486(二分图匹配)二分图的完全匹配的必须边


    题意:给你n个幻灯片,每个幻灯片有个数字编号1~n,现在给每个幻灯片用A~Z进行编号,那么问有多少个幻灯片的数字和字母是唯一对应的

    二分图的完全匹配的必须边,裸的。

    这道题目可以用

    http://www.cnblogs.com/proverbs/archive/2012/08/29/2662638.html

    方法来解。。但是我的第一反应就是删边。于是乎,用删边的方法做的

    先做一遍匹配,匈牙利。然后对于匹配中的每条边都删除一遍,如果不能达到完全匹配,则这条边是必须边。

    大致思想就是这样了

    代码里几个我犯错的地方写了注释

    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #define N 40
     5 #define M 1600
     6 using namespace std;
     7 int n,x1[N],x2[N],y1[N],y2[N],x,y,head[N],next[M],to[M],bh[N][N],ban,cnt,linky[N],first_ans,cas;
     8 bool vis[N];
     9 void add(int u,int v)
    10 {
    11     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
    12 }
    13 void read()
    14 {
    15     memset(head,-1,sizeof head);cnt=0;
    16     for(int i=1;i<=n;i++) scanf("%d%d%d%d",&x1[i],&x2[i],&y1[i],&y2[i]);
    17     for(int i=1;i<=n;i++)
    18     {
    19         scanf("%d%d",&x,&y);
    20         for(int j=1;j<=n;j++)
    21             if(x>x1[j]&&x<x2[j]&&y>y1[j]&&y<y2[j])
    22             {
    23                 bh[i][j]=cnt;//两点连线的编号 
    24                 add(i,j);
    25             }
    26     }
    27 }
    28 bool dfs(int u)
    29 {
    30     for(int i=head[u];~i;i=next[i])
    31         if(!vis[to[i]]&&ban!=i)
    32         {
    33             vis[to[i]]=true;
    34             if(linky[to[i]]==-1||dfs(linky[to[i]]))
    35             {
    36                 linky[to[i]]=u;
    37                 return true;
    38             }
    39         }
    40     return false;
    41 }
    42 void first_match()
    43 {
    44     memset(linky,-1,sizeof linky);
    45     for(int i=1;i<=n;i++)
    46     {
    47         memset(vis,0,sizeof vis);
    48         if(dfs(i)) first_ans++;
    49     }
    50 }
    51 void go()
    52 {
    53     ban=-1;
    54     first_match();
    55     bool bj=false;
    56     printf("Heap %d\n",cas);
    57     for(int i=1,tmp;i<=n;i++)
    58     {
    59         tmp=linky[i];
    60         ban=bh[tmp][i];//ban是删的边,注意tmp是左边的点,i是右边的点 
    61         linky[i]=-1;
    62         memset(vis,0,sizeof vis);
    63         if(!dfs(tmp))
    64         {
    65             bj=true,printf("(%c,%d) ",'A'+i-1,tmp);
    66             linky[i]=tmp;//必须放在括号内,因为如果dfs返回true的话说明有新的匹配,linky不能更新 
    67         }
    68     }
    69     if(bj) printf("\n\n");
    70     else printf("none\n\n");
    71 }
    72 int main()
    73 {
    74     while(scanf("%d",&n),n)
    75     {
    76         cas++;
    77         read();
    78         go();
    79     }
    80     return 0;
    81 }

    话说,我这个蒟蒻POJ终于到了300题了。。

    还是太弱,XLk神牛每天40题呢。。

    OTZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    内置对象
    Angular 动画
    Angular_上拉刷新
    angular Observable
    【Nginx】nginx为目录或网站加上密码认证
    MongoDB笔记
    websocket服务器+客户端
    cli 中php的配置和phpinfo不一样
    linux设置时区和自动同步时间
    crontab & php实现多进程思路
  • 原文地址:https://www.cnblogs.com/proverbs/p/2662798.html
Copyright © 2020-2023  润新知