zoukankan      html  css  js  c++  java
  • 二分图的拓展与应用:HDU 2819&&POJ 1486&&HDU 3488&&HDU1853

    Swap HDU 2819

    此题主要让我们发现匈牙利算法中记录匹配点编号数组的应用:

    此数组记录的是左边的第几个与右边的第几个匹配

    因为要求对角线匹配,那么进行两两移位就行了。。。

    注意的是:你把横坐标的数放在左边,竖坐标的数放在右边的话,是移动C。

    反过来就是移动R。

    具体看代码:(注意红色字体部分

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<string.h>
     5 using namespace std;
     6 int a[105][105],b[105],vis[105],a1[105],b1[105],n;
     7 int dfs(int x)
     8 {
     9     for(int i=1;i<=n;i++)
    10         if(a[i][x]&&!vis[i])
    11         {
    12             vis[i]=1;
    13             if(b[i]==-1||dfs(b[i]))
    14             {
    15                 b[i]=x;
    16                 return 1;
    17             }
    18         }
    19     return 0;
    20 }
    21 int main()
    22 {
    23     int i,j,ans,sum;
    24     while(scanf("%d",&n)!=EOF)
    25     {
    26         for(i=1;i<=n;i++)
    27             for(j=1;j<=n;j++)
    28                 scanf("%d",&a[i][j]);//这里说明横坐标在左边(i),竖坐标在右边(j)
    29         ans=0;
    30         memset(b,-1,sizeof(b));
    31         for(i=1;i<=n;i++)
    32         {
    33             memset(vis,0,sizeof(vis));
    34             if(dfs(i))
    35                 ans++;
    36         }
    37         if(ans<n)
    38         {
    39             printf("-1
    ");
    40             continue;
    41         }
    42         sum=0;
    43         for(i=1;i<=n;i++)
    44         {
    45             for(j=i;j<=n;j++)
    46                 if(b[j]==i)
    47                     break;
    48             if(i!=j)
    49             {
    50                 sum++;
    51                 a1[sum]=i;
    52                 b1[sum]=j;
    53                 swap(b[i],b[j]);
    54             }
    55         }//移位的话,是一左边为基点,一个一个把左边的移好位
    56         printf("%d
    ",sum);
    57         for(i=1;i<=sum;i++)
    58             printf("R %d %d
    ",a1[i],b1[i]);
    59     }
    60     return 0;
    61 }

    但是只要改一点点就行了!!!

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<string.h>
     5 using namespace std;
     6 int a[105][105],b[105],vis[105],a1[105],b1[105],n;
     7 int dfs(int x)
     8 {
     9     for(int i=1;i<=n;i++)
    10         if(a[x][i]&&!vis[i])
    11         {
    12             vis[i]=1;
    13             if(b[i]==-1||dfs(b[i]))
    14             {
    15                 b[i]=x;
    16                 return 1;
    17             }
    18         }
    19     return 0;
    20 }
    21 int main()
    22 {
    23     int i,j,ans,sum;
    24     while(scanf("%d",&n)!=EOF)
    25     {
    26         for(i=1;i<=n;i++)
    27             for(j=1;j<=n;j++)
    28                 scanf("%d",&a[i][j]);
    29         ans=0;
    30         memset(b,-1,sizeof(b));
    31         for(i=1;i<=n;i++)
    32         {
    33             memset(vis,0,sizeof(vis));
    34             if(dfs(i))
    35                 ans++;
    36         }
    37         if(ans<n)
    38         {
    39             printf("-1
    ");
    40             continue;
    41         }
    42         sum=0;
    43         for(i=1;i<=n;i++)
    44         {
    45             for(j=i;j<=n;j++)
    46                 if(b[j]==i)
    47                     break;
    48             if(i!=j)
    49             {
    50                 sum++;
    51                 a1[sum]=i;
    52                 b1[sum]=j;
    53                 swap(b[i],b[j]);
    54             }
    55         }
    56         printf("%d
    ",sum);
    57         for(i=1;i<=sum;i++)
    58             printf("C %d %d
    ",a1[i],b1[i]);
    59     }
    60     return 0;
    61 }

     但是我发现一个致命错误!!

    上面的第一个代码:

    没有进入dfs()的是横坐标,但是dfs()里面求的是以右括号的为定值,把左括号进行循环找出这个b[i]=x;

    可以发现b[i]表示横坐标,那么下面移位的是b[i],则就是‘R’!!

    Sorting Slides POJ 1486

    这题主要考如何判断这个匹配是唯一的?(进行删边处理)

    步骤:
    1:求最大匹配,匹配边集合E
    2:删除E中的一条边e,以e的一个端点找增广路,若不能找到增广路则e是必须边
    3:恢复原图以及E,继续步骤2,直到E中的每条边都被删除过

    分析:因为每个顶点只出现一次,那么每个顶点只关联两个顶点入度顶点和出度顶点,所以构造二分图,将一个点u拆成u,u'。那么对于这个二分图如果存在着完美匹配的话,那么原图中一定存在若干个环,环中包含每个顶点,对于权值之和最小,只需求最小权匹配即可。

    这个题目不用求出匹配数是多少。。。

    直接进行删边,有唯一的就输出。。。如果一个都没有就输出“none”。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<string.h>
     5 using namespace std;
     6 int a1[105][105],vis[105],b[105],n;
     7 struct line
     8 {
     9     int x1;
    10     int x2;
    11     int y1;
    12     int y2;
    13 }a[105];
    14 int dfs(int x)
    15 {
    16     for(int i=1;i<=n;i++)
    17         if(a1[x][i]&&!vis[i])
    18     {
    19         vis[i]=1;
    20         if(b[i]==-1||dfs(b[i]))
    21         {
    22             b[i]=x;
    23             return 1;
    24         }
    25     }
    26     return 0;
    27 }
    28 int main()
    29 {
    30     int d=0,i,j,x1,y1;
    31     while(scanf("%d",&n)!=EOF)
    32     {
    33         if(n==0)
    34             break;
    35         if(d)
    36             printf("
    ");
    37         for(i=1;i<=n;i++)
    38             scanf("%d%d%d%d",&a[i].x1,&a[i].x2,&a[i].y1,&a[i].y2);
    39         memset(a1,0,sizeof(a1));
    40         for(i=1;i<=n;i++)
    41         {
    42             scanf("%d%d",&x1,&y1);
    43             for(j=1;j<=n;j++)
    44                 if(a[j].x1<x1&&a[j].x2>x1&&a[j].y1<y1&&a[j].y2>y1)
    45                     a1[i][j]=1;
    46         }
    47         memset(b,-1,sizeof(b));
    48         for(i=1;i<=n;i++)
    49         {
    50             memset(vis,0,sizeof(vis));
    51             dfs(i);
    52         }
    53         printf("Heap %d
    ",++d);
    54         int flag=0;
    55         for(i=1;i<=n;i++)//******************
    56         {
    57             int tmp=b[i];
    58             b[i]=-1;
    59             a1[tmp][i]=0;
    60             memset(vis,0,sizeof(vis));//注意初始为零
    61             if(!dfs(tmp))
    62             {
    63                 if(flag)
    64                     printf(" ");
    65                 printf("(%c,%d)",'A'+i-1,tmp);//注意的是把代表字母放到右边,那么判断直接输出就行了
    66                 b[i]=tmp;
    67                 flag=1;
    68             }
    69             a1[tmp][i]=1;
    70         }//*********************删边处理
    71         if(flag==0)
    72             printf("none
    ");
    73         else
    74             printf("
    ");
    75 
    76     }
    77     return 0;
    78 }

     之后来个最小权匹配的例子:

    Tour  HDU 3488

    这里注意判断时,和输出时:(红色字体部分

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<string.h>
     5 using namespace std;
     6 int inf=100000005;
     7 int lx[205],ly[205],a[205][205],vix[205],viy[205],slack[205],link[205],n;
     8 int dfs(int x)
     9 {
    10     vix[x]=1;
    11     for(int i=1;i<=n;i++)
    12     {
    13         if(viy[i])
    14             continue;
    15         if(a[x][i]!=-inf&&lx[x]+ly[i]==a[x][i])
    16         {
    17             viy[i]=1;
    18             if(link[i]==-1||dfs(link[i]))
    19             {
    20                 link[i]=x;
    21                 return 1;
    22             }
    23         }
    24         else if(a[x][i]!=-inf)//这里知道一定有完美匹配了!如果没有就是个死循环
    25         {
    26             if(lx[x]+ly[i]-a[x][i]<slack[i])
    27                 slack[i]=lx[x]+ly[i]-a[x][i];
    28         }
    29     }
    30     return 0;
    31 }
    32 int main()
    33 {
    34     int t,m,a1,b1,c1,s,i,j;
    35     scanf("%d",&t);
    36     while(t--)
    37     {
    38         scanf("%d%d",&n,&m);
    39         for(i=1;i<=n;i++)
    40             for(j=1;j<=n;j++)
    41             a[i][j]=-inf;
    42         while(m--)
    43         {
    44             scanf("%d%d%d",&a1,&b1,&c1);
    45             if(a[a1][b1]<-c1)
    46                 a[a1][b1]=-c1;
    47         }
    48         memset(link,-1,sizeof(link));
    49         memset(lx,-inf,sizeof(lx));
    50         memset(ly,0,sizeof(ly));
    51         for(i=1;i<=n;i++)
    52             for(j=1;j<=n;j++)
    53             if(a[i][j]>lx[i])
    54                 lx[i]=a[i][j];
    55         for(i=1;i<=n;i++)
    56         {
    57             for(j=1;j<=n;j++)
    58                 slack[j]=inf;
    59             while(1)
    60             {
    61                 memset(vix,0,sizeof(vix));
    62                 memset(viy,0,sizeof(viy));
    63                 if(dfs(i))
    64                     break;
    65                 int d=inf;
    66                 for(j=1;j<=n;j++)
    67                     if(!viy[j]&&d>slack[j])
    68                         d=slack[j];
    69                 for(j=1;j<=n;j++)
    70                 {
    71                     if(vix[j])
    72                         lx[j]-=d;
    73                     if(viy[j])
    74                         ly[j]+=d;
    75                     else
    76                         slack[j]-=d;
    77                 }
    78             }
    79         }
    80         s=0;
    81         for(i=1;i<=n;i++)
    82             if(link[i]!=-1)
    83                 s+=a[link[i]][i];
    84         printf("%d
    ",-s);
    85     }
    86     return 0;
    87 }

     Cyclic Tour  HDU1853

    这个题目和上面的差不多,但是他不一定有完美匹配!!! 

    所以用上面的方法做不出来!!!

    所以就要套用模板什么都不用改!在最后进行判断就行了!

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<string.h>
     5 using namespace std;
     6 int inf=100000005;
     7 int lx[205],ly[205],a[205][205],vix[205],viy[205],slack[205],link[205],n;
     8 int dfs(int x)
     9 {
    10     vix[x]=1;
    11     for(int i=1;i<=n;i++)
    12     {
    13         if(viy[i])
    14             continue;
    15         if(lx[x]+ly[i]==a[x][i])
    16         {
    17             viy[i]=1;
    18             if(link[i]==-1||dfs(link[i]))
    19             {
    20                 link[i]=x;
    21                 return 1;
    22             }
    23         }
    24         else
    25         {
    26             if(lx[x]+ly[i]-a[x][i]<slack[i])
    27                 slack[i]=lx[x]+ly[i]-a[x][i];
    28         }
    29     }
    30     return 0;
    31 }
    32 int main()
    33 {
    34     int m,a1,b1,c1,s,i,j;
    35     while(scanf("%d%d",&n,&m)!=EOF)
    36     {
    37         for(i=1;i<=n;i++)
    38             for(j=1;j<=n;j++)
    39             a[i][j]=-inf;
    40         while(m--)
    41         {
    42             scanf("%d%d%d",&a1,&b1,&c1);
    43             if(a[a1][b1]<-c1)
    44                 a[a1][b1]=-c1;
    45         }
    46         memset(link,-1,sizeof(link));
    47         memset(lx,-inf,sizeof(lx));
    48         memset(ly,0,sizeof(ly));
    49         for(i=1;i<=n;i++)
    50             for(j=1;j<=n;j++)
    51             if(a[i][j]>lx[i])
    52                 lx[i]=a[i][j];
    53         for(i=1;i<=n;i++)
    54         {
    55             for(j=1;j<=n;j++)
    56                 slack[j]=inf;
    57             while(1)
    58             {
    59                 memset(vix,0,sizeof(vix));
    60                 memset(viy,0,sizeof(viy));
    61                 if(dfs(i))
    62                     break;
    63                 int d=inf;
    64                 for(j=1;j<=n;j++)
    65                     if(!viy[j]&&d>slack[j])
    66                         d=slack[j];
    67                 for(j=1;j<=n;j++)
    68                 {
    69                     if(vix[j])
    70                         lx[j]-=d;
    71                     if(viy[j])
    72                         ly[j]+=d;
    73                     else
    74                         slack[j]-=d;
    75                 }
    76             }
    77         }
    78         s=0;
    79         int s1=0;
    80         for(i=1;i<=n;i++)//***********
    81             {
    82                 if(link[i]==-1||a[link[i]][i]==-inf)
    83                 {
    84                     s1=1;
    85                     break;
    86                 }
    87                 s+=a[link[i]][i];
    88             }//****************
    89         if(s1==1)
    90             printf("-1
    ");
    91         else
    92             printf("%d
    ",-s);
    93     }
    94     return 0;
    95 }
  • 相关阅读:
    5.3Python解析动态页面源代码
    5.2
    5.1selenium
    团队项目第一阶段冲刺第十天
    团队项目第一阶段冲刺第九天
    4.30线程和进程
    团队项目第一阶段冲刺第八天
    Mac下全局安装yarn,报错,没有访问权限解决办法
    Mac下的常用命令行
    I Term2常用快捷键
  • 原文地址:https://www.cnblogs.com/tt123/p/3269774.html
Copyright © 2011-2022 走看看