zoukankan      html  css  js  c++  java
  • 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:
    ",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
  • 相关阅读:
    IIS7中的几种身份鉴别方式(一)Basic身份验证
    IIS7中的几种身份鉴别方式(二)集成身份验证
    java集合
    SharePoint 2010中welcome page的设置细节
    SharePoint中使用Linq出现未将对象引用到实例化的解决方法
    SharePoint 2010中关于An error was encountered while retrieving the user profile的处理方式记录
    The Need for an Architectural Body of Knowledge
    The Softer Side of the Architect
    Event Receivers 学习小结
    使用SmtpClient发送带图片的邮件的代码实现
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3264386.html
Copyright © 2011-2022 走看看