HDU4687 Boke and Tsukkomi

题目链接:https://vjudge.net/problem/HDU-4687

知识点:  带花树开花算法

解题思路:

  先求出原来的一般图的最大匹配数\(iCnt\). 然后枚举每一个组合,尝试去掉图中所有以这个组合中任意一点为端点的边,求出此时的最大匹配数\(tCnt\),如果\(tCnt<iCnt-1\),则这个组合对于任意一种最大匹配来说都是多余的。

AC代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef pair<int,int> P ;
  4 const int maxn = 40+5, maxm = 150;
  5 int N,M;
  6 bool Graph[maxn][maxn],G[maxn][maxn];
  7 int Match[maxn];
  8 bool InQueue[maxn],InPath[maxn],InBlossom[maxn];
  9 int Head,Tail;
 10 int Queue[maxn];
 11 int Start,Finish;
 12 int NewBase;
 13 int Father[maxn],Base[maxn];
 14
 15 P inp[maxm];
 16
 17 void Push(int u){
 18     Queue[Tail]=u;
 19     Tail++;
 20     InQueue[u]=true;
 21 }
 22 int Pop(){
 23     int res=Queue[Head];
 24     Head++;
 25     return res;
 26 }
 27 int FindCommonAncestor(int u,int v){
 28     memset(InPath,false,sizeof(InPath));
 29     while(1){
 30         u=Base[u];
 31         InPath[u]=true;
 32         if(u==Start)    break;
 33         u=Father[Match[u]];
 34     }
 35     while(1){
 36         v=Base[v];
 37         if(InPath[v])   break;
 38         v=Father[Match[v]];
 39     }
 40     return v;
 41 }
 42 void ResetTrace(int u){
 43     int v;
 44     while(Base[u]!=NewBase){
 45         v=Match[u];
 46         InBlossom[Base[u]]=InBlossom[Base[v]]=true;
 47         u=Father[v];
 48         if(Base[u]!=NewBase)    Father[u]=v;
 49     }
 50 }
 51 void BloosomContract(int u,int v){
 52     NewBase = FindCommonAncestor(u,v);
 53     memset(InBlossom,false,sizeof(InBlossom));
 54     ResetTrace(u);  ResetTrace(v);
 55     if(Base[u]!=NewBase)    Father[u]=v;
 56     if(Base[v]!=NewBase)    Father[v]=u;
 57     for(int tu=1;tu<=N;tu++){
 58         if(InBlossom[Base[tu]]){
 59             Base[tu]=NewBase;
 60             if(!InQueue[tu])    Push(tu);
 61         }
 62     }
 63 }
 64 void FindAugmentingPath(){
 65     memset(InQueue,false,sizeof(InQueue));
 66     memset(Father,0,sizeof(Father));
 67     for(int i=1;i<=N;i++)   Base[i]=i;
 68     Head=Tail=1;
 69     Push(Start);
 70     Finish=0;
 71     while(Head<Tail){
 72         int u=Pop();
 73         for(int v=1;v<=N;v++){
 74             if(Graph[u][v]&&(Base[u]!=Base[v])&&(Match[u]!=v)){
 75                 if((v==Start)||(Match[v]>0)&&(Father[Match[v]]>0))
 76                     BloosomContract(u,v);
 77                 else if(Father[v]==0){
 78                     Father[v]=u;
 79                     if(Match[v]>0)  Push(Match[v]);
 80                     else{
 81                         Finish=v;
 82                         return;
 83                     }
 84                 }
 85             }
 86         }
 87     }
 88 }
 89 void AugumentPath(){
 90     int u,v,w;
 91     u=Finish;
 92     while(u>0){
 93         v=Father[u];
 94         w=Match[v];
 95         Match[v]=u;
 96         Match[u]=v;
 97         u=w;
 98     }
 99 }
100 void Edmonds(){
101     memset(Match,0,sizeof(Match));
102     for(int u=1;u<=N;u++){
103         if(Match[u]==0){
104             Start =u;
105             FindAugmentingPath();
106             if(Finish>0)    AugumentPath();
107         }
108     }
109 }
110
111 int main(){
112     int u,v;
113     while(scanf("%d%d",&N,&M)==2){
114         memset(G,false,sizeof(G));
115         memset(Graph,false,sizeof(Graph));
116         for(int i=1;i<=M;i++){
117             scanf("%d%d",&u,&v);
118             inp[i]=make_pair(u,v);
119             Graph[u][v]=Graph[v][u]=G[u][v]=G[v][u]=true;
120         }
121         Edmonds();
122         int iCount=0;
123         for(int u=1;u<=N;u++){
124             if(Match[u]>0)  iCount++;
125         }iCount/=2;
126         vector<int> ans;
127         for(int i=1;i<=M;i++){
128             int u=inp[i].first,v=inp[i].second;
129             for(int j=1;j<=N;j++)   Graph[u][j]=Graph[j][u]=Graph[v][j]=Graph[j][v]=false;
130             Edmonds();
131             int tCount=0;
132             for(int u=1;u<=N;u++){
133                 if(Match[u]>0)  tCount++;
134             }tCount/=2;
135             if(tCount<iCount-1) ans.push_back(i);
136             for(int j=1;j<=N;j++){
137                 Graph[u][j]=G[u][j];
138                 Graph[j][u]=G[j][u];
139                 Graph[v][j]=G[v][j];
140                 Graph[j][v]=G[j][v];
141             }
142         }
143         int sz=ans.size();
144         printf("%d\n",sz);
145         for(int i=0;i<sz;i++){
146             if(i!=0)    printf(" ");
147             printf("%d",ans[i]);
148         }
149         printf("\n");
150     }
151     return 0;
152 }

  

原文地址:https://www.cnblogs.com/Blogggggg/p/8414271.html

时间: 2024-10-15 14:44:12

HDU4687 Boke and Tsukkomi的相关文章

HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 如果C2+2==C1则这条边再某个最大匹配中 Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 649    Accepted Submission(s): 202

HDU 4687 Boke and Tsukkomi(一般图匹配|带花树)

比赛的时候刚开始看这题还以为是二分图匹配,后来才发现根本不是,因为该题存在长度为奇数的圈 .  比如1->2,2->3,3->1 . 所以该题要用一般图匹配,即带花树算法 . 比赛时抄的模板有地方抄错了,上述样例出现了死循环 .   赛后补题的时候用map去重却得不到正确答案,不知为何,暂放 ,下面给出一种正确解法. 细节参见代码: #include<cstdio> #include<cstring> #include<iostream> #inclu

HDU 4687 Boke and Tsukkomi 一般图匹配,带花树,思路,输出注意空行 难度:4

http://acm.hdu.edu.cn/showproblem.php?pid=4687 此题求哪些边在任何一般图极大匹配中都无用,对于任意一条边i,设i的两个端点分别为si,ti, 则任意一个极大匹配中都必然有si或ti至少一个点被匹配,当在图中去掉si,ti两个点时,匹配数会损失一个或两个. 如果损失两个,就说明在极大匹配中这两个点分别连接不同的边,于是边i是无用的 所以总体思路:一般图匹配求出最大匹配数cnt0,分别试着去掉每条边的端点,再次匹配,匹配数如果小于cnt0-1,则这条边无

kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图. 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知道什么是最小点覆盖,我也在这里说一下:假如选

一般图匹配带花树

R - Work Scheduling Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice URAL 1099 Appoint description: Description There is certain amount of night guards that are available to protect the local junkyard

[kuangbin]带你飞之&#39;匹配问题&#39;专题

带飞网址 ? 专题十 匹配问题 √ HDU 1045 Fire NetHDU 2444 The Accomodation of StudentsHDU 1083 CoursesHDU 1281 棋盘游戏HDU 2819 SwapHDU 2389 Rain on your ParadeHDU 4185 Oil SkimmingPOJ 3020 Antenna PlacementHDU 1054 Strategic GameHDU 1151 Air RaidPOJ 2594 Treasure Exp

boke

云/n 计算/v 代表/n IT/x 领域/n 向/p 集约化/v ./w 规模化/v 与/c 专业化/v 道路/n 发展/v 的/u 趋势/n ,/w 是/v IT/x 领域/n 正在/d 发生/v 的/u 深刻/a 变革/v ./w 但/c 它/r 在/p 提高/v 使用/v 效率/n 的/u 同时/n ,/w 为/p 实现/v 用户/n 信息/n 资产/n 安全/a 与/c 隐私/n 保护/v 带来/v 极大/a 的/u 冲击/v 与/c 挑战/v ./w 当前/t ,/w 安全/a 成为

我的第一次boke

html —— 超文本标记语言 标准的格式 如果出现小的编码错误 系统会自动帮你纠正 htm —— 一些较老的服务器,只有支持后缀为三位 xhtml—— 严格的html 格式 Meta 标签: <meta name="Keywords" content="学生成绩"> 向搜索引擎说明网页的关键字 如果搜索学生成绩 那么就对抓取到这个网页 如果输入其他的则无法搜索到 <meta name="Description" content

try~Catch语句中异常的处理过程

[2014/10/12 21:40]文章待续~ 1.函数自身捕获处理异常的情况 下面的例子介绍了try~catch语句中出现异常时语句的执行顺序: package month10; import java.lang.*; public class TryCatch{ /* * 函数产生一个ArithmeticException异常 */ public static void First(){ System.out.println("第一个异常处理的例子"); try{ //double