2013 ACM/ICPC Asia Regional Changsha Online - I Grand Prix

来源:互联网 发布:vmware桥接网络设置 编辑:程序博客网 时间:2024/05/01 09:03

离正解非常非常接近就差一步的感觉真让人忧伤_(:3」∠)_

第一步肯定是求出最大匹配,数据范围挺大,连Dinic都超时,只能使用Hopcroft-Karp算法来求。


求出最大匹配ans后,先是一个朴素的想法。

枚举每条不是匹配的边(u,v),把它强行匹配,就是删去u,v两点,看新图的最大匹配数是否是ans-1,是的话它就可能出现在最大匹配中。

但这样的时间复杂度明显过大。


删去了u和v两点至多删去两个匹配,如果新图的匹配是ans-1就意味着u,v两点原来匹配的两点可以找到一条增广路径。

先假设用的就是dinic算法求的匹配,那么很明显的是(u,v)是最大匹配等价于有条从v到u的路,反之则有条从u到v的路。

所以每次询问u到v是否有路时,一定存在边(v,u),故问题等价于判断u与vv是否可以相互到达。


综上只需要把Hopcroft-Karp求出匹配的结果还原到网络流上,并在这个图上求出强连通分量,对于每条非匹配边,判断u和v不在一个SCC里面,

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <cstdlib>#include <cmath>#include <cctype>#include <queue>#include <stack>#include <map>#include <set>#include <list>#define pb push_back#define mp make_pair#define fi first#define se second//#pragma comment(linker, "/STACK:16777216")using namespace std;typedef long long LL;typedef unsigned long long ULL;#define N 40005#define M 1000005int n , m , p , s , t , ans;pair<int , int> ee[200000];struct arc{  int x , next;}e[M] , g[M];int pre[N] , mcnt , tmp[N] , ncnt;void addarc(int x ,int y){  e[mcnt] = (arc) {y , pre[x]} , pre[x] = mcnt ++;}void addedge(int x ,int y){  g[ncnt] = (arc) {y , tmp[x]} , tmp[x] = ncnt ++;}int mx[N] , my[N];queue<int> que;int dx[N] , dy[N];bool vis[N];bool find(int x){    for (int i = pre[x] ; ~i ; i = e[i].next)    {        int y = e[i].x;        if (!vis[y] && dy[y] == dx[x] + 1)        {            vis[y] = 1;            if (!~my[y] || find(my[y]))            {                mx[x] = y , my[y] = x;                return 1;            }        }    }    return 0;}int matching(){    memset(mx , -1 , sizeof(mx));    memset(my , -1 , sizeof(my));    int ans = 0;    while (1){        bool flag = 0;        while (!que.empty()) que.pop();        memset(dx , 0 , sizeof(dx));        memset(dy , 0 , sizeof(dy));        for (int i = 0 ; i < n ; ++ i)            if (!~mx[i]) que.push(i);        while (!que.empty())        {            int x = que.front(); que.pop();            for (int i = pre[x] ; ~i ; i = e[i].next)            {                int y = e[i].x;                if (!dy[y])                {                    dy[y] = dx[x] + 1 ;                    if (~my[y])                        que.push(my[y]) , dx[my[y]] = dy[y] + 1;                    else                        flag = 1;                }            }        }        if (!flag) break;        memset(vis , 0 , sizeof(vis));        for (int i = 0 ; i < n ; ++ i)            if (!~mx[i] && find(i)) ++ ans;    }    return ans;}int idx , scnt , low[N] , DFN[N] , bel[N];stack<int> st; bool is[N];void tarjan(int x){  int i , y;  DFN[x] = low[x] = ++ idx;  is[x] = 1 , st.push(x);  for (i = tmp[x] ; ~i ; i = g[i].next)  {    y = g[i].x;    if (!DFN[y])    {      tarjan(y);      low[x] = min(low[x] , low[y]);    }    else if (is[y])      low[x] = min(low[x] , DFN[y]);  }  if (DFN[x] == low[x])  {    scnt ++;    do    {      i = st.top() , st.pop();      is[i] = 0 , bel[i] = scnt;    }while (x != i);  }}char str[10];vector<int> res;void work(){  int i , j , x , y;  scanf("%d%d",&m,&p);  memset(pre , -1 , sizeof(pre)) , mcnt = 0;  s = n + m , t = s + 1;  for (i = 0 ; i < p ; ++ i)  {    scanf("%s" , str);    x = y = 0;    for (j = 0 ; j < 3 ; ++ j)    {      x <<= 5;      if (isdigit(str[j]))        x |= (str[j] - '0');      else  x |= (str[j] - 'A' + 10);    }    for (j = 3 ; j < 6 ; ++ j)    {      y <<= 5;      if (isdigit(str[j]))        y |= (str[j] - '0');      else  y |= (str[j] - 'A' + 10);    }    ee[i] = make_pair(x , y);    addarc(x , n + y);  }  res.clear();  ans = matching();  memset(tmp , -1 , sizeof(tmp)) , ncnt = 0;  for (i = 0 ; i < n ; ++ i)    if (!~mx[i])       addedge(s , i);    else addedge(i , s);  for (i = n ; i < n + m ; ++ i)    if (!~my[i])       addedge(i , t);    else addedge(t , i);  for (x = 0 ; x < n ; ++ x)    for (i = pre[x] ; ~i ; i = e[i].next)      if (mx[x] != e[i].x)        addedge(x , e[i].x);      else addedge(e[i].x , x);  scnt = idx = 0;  memset(low , 0 , sizeof(low));  memset(DFN , 0 , sizeof(DFN));  for (i = 0 ; i <= t ; ++ i)    if (!DFN[i])      tarjan(i);  for (i = 0 ; i < p ; ++ i)  {    x = ee[i].fi , y = ee[i].se;    if (mx[x] == y + n) continue;    if (bel[x] != bel[y + n])        res.push_back(i);  }  printf("%d\n" ,res.size());  for (i = 0 ; i < res.size() ; ++ i)  {    if (i) printf(" ");    printf("%d" , res[i]);  }  printf("\n");}int main(){    //freopen("~input.txt" , "r" , stdin);    //int _; scanf("%d\n",&_); while (_--)    while (~scanf("%d",&n))        work();    return 0;}


原创粉丝点击