hdu 4685 Prince and Princess (2013.8.15 多校8---1010)

http://acm.hdu.edu.cn/showproblem.php?pid=4685

先找最大匹配数ret

然后把将n这一边的大于n的m-ret与m这一边的n+m-ret边连起来,将n这一边的n+m-ret与m这一边的大于m的n-ret连起来,做最大匹配,得到一个匹配

然后根据这个匹配找强连通分量,属于同一强连通分量的priceness和price可以任意配

同一强连通分量的所有priceness可以给同一强连通分量的price。

用hopcroft-karp算法890ms,用匈牙利算法2656ms。。。

顺便在代码中附上hopcroft-karp算法和找强连通分量的模板~

复制代码
  1 /**
  2 *先找最大匹配ret
  3 *然后把将n和m以上的n+m-ret边连起来做最大匹配
  4 *然后按这个匹配找强连通分量,属于同一强连通分量的priceness和price可以任意配
  5 *
  6 *@Author: xiaohai---xysmlx
  7 */
  8 //#pragma comment(linker, "/STACK:102400000,102400000")
  9 #include<cstdio>
 10 #include<iostream>
 11 #include<cstring>
 12 #include<string>
 13 #include<cmath>
 14 #include<set>
 15 #include<list>
 16 #include<map>
 17 #include<iterator>
 18 #include<cstdlib>
 19 #include<vector>
 20 #include<queue>
 21 #include<stack>
 22 #include<algorithm>
 23 #include<functional>
 24 using namespace std;
 25 typedef long long LL;
 26 #define ROUND(x) round(x)
 27 #define FLOOR(x) floor(x)
 28 #define CEIL(x) ceil(x)
 29 const int maxn=1010;
 30 const int maxm=maxn*maxn;
 31 const int inf=0x3f3f3f3f;
 32 const LL inf64=0x3f3f3f3f3f3f3f3fLL;
 33 const double INF=1e30;
 34 const double eps=1e-6;
 35 
 36 /**
 37 *大数据二分图匹配:Hopcroft-Karp($O(\sqrt{V}E)$)
 38 *适用于数据较大的二分匹配(从0到n-1)
 39 *输入:Nx,Ny,g[][]
 40 *输出:res=MaxMatch();
 41 */
 42 int g[maxn][maxn],Mx[maxn],My[maxn],Nx,Ny;
 43 int dx[maxn],dy[maxn],dis;
 44 bool vst[maxn];
 45 int res;
 46 bool searchP()
 47 {
 48     queue<int>Q;
 49     dis=inf;
 50     memset(dx,-1,sizeof(dx));
 51     memset(dy,-1,sizeof(dy));
 52     for(int i=0; i<Nx; i++)
 53         if(Mx[i]==-1)
 54         {
 55             Q.push(i);
 56             dx[i]=0;
 57         }
 58     while(!Q.empty())
 59     {
 60         int u=Q.front();
 61         Q.pop();
 62         if(dx[u]>dis)  break;
 63         for(int v=0; v<Ny; v++)
 64             if(g[u][v]&&dy[v]==-1)
 65             {
 66                 dy[v]=dx[u]+1;
 67                 if(My[v]==-1)  dis=dy[v];
 68                 else
 69                 {
 70                     dx[My[v]]=dy[v]+1;
 71                     Q.push(My[v]);
 72                 }
 73             }
 74     }
 75     return dis!=inf;
 76 }
 77 bool DFS(int u)
 78 {
 79     for(int v=0; v<Ny; v++)
 80         if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
 81         {
 82             vst[v]=1;
 83             if(My[v]!=-1&&dy[v]==dis) continue;
 84             if(My[v]==-1||DFS(My[v]))
 85             {
 86                 My[v]=u;
 87                 Mx[u]=v;
 88                 return 1;
 89             }
 90         }
 91     return 0;
 92 }
 93 int MaxMatch()
 94 {
 95     int res=0;
 96     memset(Mx,-1,sizeof(Mx));
 97     memset(My,-1,sizeof(My));
 98     while(searchP())
 99     {
100         memset(vst,0,sizeof(vst));
101         for(int i=0; i<Nx; i++)
102             if(Mx[i]==-1&&DFS(i))  res++;
103     }
104     return res;
105 }
106 
107 /**
108 *有向图强连通分量:Tarjan算法($O(V+E)$)
109 *输入:图(从0到n-1)
110 *输出:sid[](强连通分量标号)
111 */
112 //const int maxn=0;
113 //const int maxm=0;
114 struct Edge
115 {
116     int v,w;
117     int next;
118 } edge[maxm];
119 int head[maxn],edgeNum;
120 void addSubEdge(int u,int v)
121 {
122     edge[edgeNum].v=v;
123     edge[edgeNum].next=head[u];
124     head[u]=edgeNum++;
125 }
126 void addEdge(int u,int v)
127 {
128     addSubEdge(u,v);
129     addSubEdge(v,u);
130 }
131 int sid[maxn];
132 int mark[maxn],low[maxn];
133 int check[maxn];
134 int sstack[maxn],top;
135 int dfn,ssn;
136 int n,m;
137 void dfs(int k)
138 {
139     int i,j;
140     check[k]=1;
141     low[k]=mark[k]=dfn++;
142     sstack[top++]=k;
143     for(int i=head[k]; i!=-1; i=edge[i].next)
144     {
145         int j=edge[i].v;
146         if(mark[j]==0)
147         {
148             dfs(j);
149             low[k]=min(low[k],low[j]);
150         }
151         else if(check[j])
152             low[k]=min(low[k],mark[j]);
153     }
154     if(mark[k]==low[k])
155     {
156         while(sstack[--top]!=k)
157         {
158             check[sstack[top]]=0;
159             sid[sstack[top]]=ssn;
160         }
161         sid[k]=ssn;
162         check[k]=0;
163         ++ssn;
164     }
165     return;
166 }
167 void tarjan()
168 {
169     ssn=1;
170     dfn=1;
171     top=0;
172     memset(check,0,sizeof(check));
173     memset(mark,0,sizeof(mark));
174     for(int i=0; i<n; ++i) if(mark[i]==0) dfs(i);
175 }
176 
177 int N,M;
178 void init()
179 {
180     memset(g,0,sizeof(g));
181     memset(head,-1,sizeof(head));
182     edgeNum=0;
183 }
184 void input()
185 {
186     scanf("%d%d",&N,&M);
187     Nx=N;
188     Ny=M;
189     for(int i=0; i<Nx; i++)
190     {
191         int k;
192         scanf("%d",&k);
193         while(k--)
194         {
195             int x;
196             scanf("%d",&x);
197             g[i][x-1]=1;
198         }
199     }
200 }
201 void solve()
202 {
203     res=MaxMatch();
204 //    cout<<res<<endl;
205     Nx=Ny=N+M-res;
206     for(int i=N; i<Nx; i++)
207     {
208         for(int j=0; j<Ny; j++)
209         {
210             g[i][j]=1;
211         }
212     }
213     for(int i=0; i<Nx; i++)
214     {
215         for(int j=M; j<Ny; j++)
216         {
217             g[i][j]=1;
218         }
219     }
220     res=MaxMatch();
221 //    cout<<res<<endl;
222 //    for(int i=0; i<Nx; i++) cout<<Mx[i]<<" ";
223 //    cout<<endl;
224 
225     for(int i=0; i<Nx; i++)
226     {
227         for(int j=0; j<Ny; j++)
228         {
229             if(g[i][j]&&j!=Mx[i])
230             {
231                 addSubEdge(Mx[i],j);
232             }
233         }
234     }
235     n=Ny;
236     tarjan();
237 //    for(int i=0;i<n;i++) cout<<sid[i]<<" ";
238 //    cout<<endl;
239 }
240 int main()
241 {
242 //    freopen("in.cpp","r",stdin);
243     int T;
244     scanf("%d",&T);
245     for(int kase=1; kase<=T; kase++)
246     {
247         init();
248         input();
249         solve();
250 
251         printf("Case #%d:\n",kase);
252         vector<int> ans;
253         for(int i=0; i<N; i++)
254         {
255             ans.clear();
256             for(int j=0; j<M; j++)
257             {
258                 if(g[i][j]&&sid[Mx[i]]==sid[j])
259                 {
260                     ans.push_back(j+1);
261                 }
262             }
263             printf("%d",ans.size());
264             for(int i=0; i<ans.size(); i++)
265             {
266                 printf(" %d",ans[i]);
267             }
268             puts("");
269         }
270     }
271     return 0;
272 }
View Code
复制代码

 

posted @   xysmlx  阅读(349)  评论(0编辑  收藏  举报
编辑推荐:
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!
点击右上角即可分享
微信分享提示