• 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
  • 相关阅读:
    Java Properties 类读配置文件保持顺序
    mysql在增加列前进行判断该列是否存在
    java中用jdom创建xml文档/将数据写入XML中
    JavaFX 简介
    ActiveMQ详细入门使用教程
    Jquery Pagination分页插件使用
    Jquery选择器总结
    自己4月份面试的一些总结
    Java面试题全集(下)转载
    Java面试题全集(上)转载
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3264386.html
Copyright © 2020-2023  润新知