hdu 4685 Prince and Princess (2013.8.15 多校8---1010)
2013-08-17 14:31
495 查看
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算法和找强连通分量的模板~
View Code
先找最大匹配数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算法和找强连通分量的模板~
/** *先找最大匹配ret *然后把将n和m以上的n+m-ret边连起来做最大匹配 *然后按这个匹配找强连通分量,属于同一强连通分量的priceness和price可以任意配 * *@Author: xiaohai---xysmlx */ //#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<iostream> #include<cstring> #include<string> #include<cmath> #include<set> #include<list> #include<map> #include<iterator> #include<cstdlib> #include<vector> #include<queue> #include<stack> #include<algorithm> #include<functional> using namespace std; typedef long long LL; #define ROUND(x) round(x) #define FLOOR(x) floor(x) #define CEIL(x) ceil(x) const int maxn=1010; const int maxm=maxn*maxn; const int inf=0x3f3f3f3f; const LL inf64=0x3f3f3f3f3f3f3f3fLL; const double INF=1e30; const double eps=1e-6; /** *大数据二分图匹配:Hopcroft-Karp($O(\sqrt{V}E)$) *适用于数据较大的二分匹配(从0到n-1) *输入:Nx,Ny,g[][] *输出:res=MaxMatch(); */ int g[maxn][maxn],Mx[maxn],My[maxn],Nx,Ny; int dx[maxn],dy[maxn],dis; bool vst[maxn]; int res; bool searchP() { queue<int>Q; dis=inf; memset(dx,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); for(int i=0; i<Nx; i++) if(Mx[i]==-1) { Q.push(i); dx[i]=0; } while(!Q.empty()) { int u=Q.front(); Q.pop(); if(dx[u]>dis) break; for(int v=0; v<Ny; v++) if(g[u][v]&&dy[v]==-1) { dy[v]=dx[u]+1; if(My[v]==-1) dis=dy[v]; else { dx[My[v]]=dy[v]+1; Q.push(My[v]); } } } return dis!=inf; } bool DFS(int u) { for(int v=0; v<Ny; v++) if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1) { vst[v]=1; if(My[v]!=-1&&dy[v]==dis) continue; if(My[v]==-1||DFS(My[v])) { My[v]=u; Mx[u]=v; return 1; } } return 0; } int MaxMatch() { int res=0; memset(Mx,-1,sizeof(Mx)); memset(My,-1,sizeof(My)); while(searchP()) { memset(vst,0,sizeof(vst)); for(int i=0; i<Nx; i++) if(Mx[i]==-1&&DFS(i)) res++; } return res; } /** *有向图强连通分量:Tarjan算法($O(V+E)$) *输入:图(从0到n-1) *输出:sid[](强连通分量标号) */ //const int maxn=0; //const int maxm=0; struct Edge { int v,w; int next; } edge[maxm]; int head[maxn],edgeNum; void addSubEdge(int u,int v) { edge[edgeNum].v=v; edge[edgeNum].next=head[u]; head[u]=edgeNum++; } void addEdge(int u,int v) { addSubEdge(u,v); addSubEdge(v,u); } int sid[maxn]; int mark[maxn],low[maxn]; int check[maxn]; int sstack[maxn],top; int dfn,ssn; int n,m; void dfs(int k) { int i,j; check[k]=1; low[k]=mark[k]=dfn++; sstack[top++]=k; for(int i=head[k]; i!=-1; i=edge[i].next) { int j=edge[i].v; if(mark[j]==0) { dfs(j); low[k]=min(low[k],low[j]); } else if(check[j]) low[k]=min(low[k],mark[j]); } if(mark[k]==low[k]) { while(sstack[--top]!=k) { check[sstack[top]]=0; sid[sstack[top]]=ssn; } sid[k]=ssn; check[k]=0; ++ssn; } return; } void tarjan() { ssn=1; dfn=1; top=0; memset(check,0,sizeof(check)); memset(mark,0,sizeof(mark)); for(int i=0; i<n; ++i) if(mark[i]==0) dfs(i); } int N,M; void init() { memset(g,0,sizeof(g)); memset(head,-1,sizeof(head)); edgeNum=0; } void input() { scanf("%d%d",&N,&M); Nx=N; Ny=M; for(int i=0; i<Nx; i++) { int k; scanf("%d",&k); while(k--) { int x; scanf("%d",&x); g[i][x-1]=1; } } } void solve() { res=MaxMatch(); // cout<<res<<endl; Nx=Ny=N+M-res; for(int i=N; i<Nx; i++) { for(int j=0; j<Ny; j++) { g[i][j]=1; } } for(int i=0; i<Nx; i++) { for(int j=M; j<Ny; j++) { g[i][j]=1; } } res=MaxMatch(); // cout<<res<<endl; // for(int i=0; i<Nx; i++) cout<<Mx[i]<<" "; // cout<<endl; for(int i=0; i<Nx; i++) { for(int j=0; j<Ny; j++) { if(g[i][j]&&j!=Mx[i]) { addSubEdge(Mx[i],j); } } } n=Ny; tarjan(); // for(int i=0;i<n;i++) cout<<sid[i]<<" "; // cout<<endl; } int main() { // freopen("in.cpp","r",stdin); int T; scanf("%d",&T); for(int kase=1; kase<=T; kase++) { init(); input(); solve(); printf("Case #%d:\n",kase); vector<int> ans; for(int i=0; i<N; i++) { ans.clear(); for(int j=0; j<M; j++) { if(g[i][j]&&sid[Mx[i]]==sid[j]) { ans.push_back(j+1); } } printf("%d",ans.size()); for(int i=0; i<ans.size(); i++) { printf(" %d",ans[i]); } puts(""); } } return 0; }
View Code
相关文章推荐
- HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)
- H - Prince and Princess - HDU 4685(二分匹配+强连通分量)
- HDU-4685-Prince and Princess(二分匹配+强连通分量)
- hdu 4685 Prince and Princess
- HDU 4685 Prince and Princess
- 【强连通】 HDU 4685 Prince and Princess
- 【hdu】4685 Prince and Princess【二分匹配+tarjan】
- HDU 4685 Prince and Princess
- HDU 4685 Prince and Princess(二分图+强连通分量)
- hdu 4685 Prince and Princess(最大匹配+强连通)
- hdu 4685 Prince and Princess(最大匹配+强连通所点,5级)
- HDU 4685 Prince and Princess
- hdu 4685 Prince and Princess(二分图匹配 + 强连通)
- HDU 4685 Prince and Princess (二分图匹配 + 强连通分量)
- HDU 4685 Prince and Princess
- hdu 4685 Prince and Princess(最大匹配+强连通所点,5级)
- hdu 4685 Prince and Princess(完美匹配+SCC缩点)
- hdu 4685 Prince and Princess 【匈牙利算法-匹配、强连通分量-Tarjan-缩点】
- hdu 4685 Prince and Princess(Tarjan+二分匹配)
- HDU 4685 Prince and Princess(最大匹配+强连通分量)