EOJ3652乘法还原(二分图)

Posted myx12345

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EOJ3652乘法还原(二分图)相关的知识,希望对你有一定的参考价值。

题意:

技术分享图片

思路:Orz Claris

先找出所有平方项,将与有平方项的数有关的数对暂时忽略,剩下的直接连边就是一张二分图,暴力DFS染色

将有平方项的数两边都加一个,再判字典序即可

我不会判字典序……耽误了一个下午

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<string>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<map>
  8 #include<set>
  9 #include<queue>
 10 #include<vector>
 11 #include<bitset>
 12 #include<ctime>
 13 using namespace std;
 14 typedef long long ll;
 15 typedef unsigned int uint;
 16 typedef unsigned long long ull;
 17 typedef pair<int,int> PII;
 18 typedef vector<int> VI;
 19 #define fi first
 20 #define se second 
 21 #define MP make_pair
 22 #define N      410000
 23 #define M      51
 24 #define MOD 1000000007
 25 #define eps 1e-8 
 26 #define pi     acos(-1)
 27 #define oo     1e9
 28 
 29 int Data[N],a[N],b[N],x[N],y[N],c[N],flag[N];
 30 vector<int>q[N];
 31 
 32 void prepare(int *x,int n) 
 33 {
 34     for(int i=1;i<=n;i++) Data[i]=x[i];
 35     sort(Data+1,Data+n+1);    
 36     int m=unique(Data+1,Data+n+1)-Data-1;
 37     for(int i=1;i<=n;i++) x[i]=lower_bound(Data+1,Data+m+1,x[i])-Data;
 38 }
 39 
 40 void dfs(int u)
 41 {
 42     if(!flag[u]) flag[u]=1;
 43     for(int i=0;i<=(int)q[u].size()-1;i++)
 44     {
 45         int v=q[u][i];
 46         if(!flag[v])
 47         {
 48             flag[v]=3-flag[u];
 49             dfs(v);
 50         }
 51     }
 52 }
 53 
 54 int main()
 55 {
 56     //freopen("D.in","r",stdin);
 57     //freopen("D.out","w",stdout);
 58     int n;
 59     scanf("%d",&n);
 60     int m=0;
 61     for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
 62     for(int i=1;i<=n;i++) a[++m]=x[i];
 63     for(int i=1;i<=n;i++) a[++m]=y[i];    
 64     for(int i=1;i<=m;i++) b[i]=a[i]; 
 65     prepare(a,m);
 66     for(int i=1;i<=n;i++) x[i]=a[i];
 67     for(int i=1;i<=n;i++) y[i]=a[i+n];
 68     for(int i=1;i<=m;i++) c[a[i]]=b[i];
 69 
 70     m=0;
 71     for(int i=1;i<=n*2;i++) m=max(m,a[i]);
 72     memset(a,0,sizeof(a));
 73     for(int i=1;i<=n;i++)
 74      if(x[i]==y[i]) a[x[i]]=1;
 75     for(int i=1;i<=m;i++) q[i].clear();
 76     for(int i=1;i<=n;i++)
 77      if(!a[x[i]]&&!a[y[i]]) 
 78      {
 79           q[x[i]].push_back(y[i]);
 80           q[y[i]].push_back(x[i]);
 81      }
 82     memset(flag,0,sizeof(flag));
 83     for(int i=1;i<=m;i++)
 84      if(!flag[i]&&!a[i]) dfs(i);
 85     int n1=0,n2=0;
 86     memset(x,0,sizeof(x));
 87     memset(y,0,sizeof(y));
 88     for(int i=1;i<=m;i++)
 89     {
 90         if(flag[i]==1) x[++n1]=i;
 91           if(flag[i]==2) y[++n2]=i;
 92     }
 93     for(int i=1;i<=m;i++)
 94      if(a[i]==1) 
 95      {
 96          x[++n1]=i;
 97         y[++n2]=i;
 98      }
 99     sort(x+1,x+n1+1);
100     sort(y+1,y+n2+1); 
101     if(n1==n2)
102     {
103         int flag=0;
104         for(int i=1;i<=n1;i++)
105         {
106             if(x[i]<y[i]) break;
107              if(x[i]>y[i]){flag=1; break;}
108         }
109         if(flag)
110          for(int i=1;i<=n1;i++) swap(x[i],y[i]);
111         
112     }
113     if(n1>n2)
114     
115     
116     {
117         for(int i=1;i<=n1;i++) swap(x[i],y[i]);
118         swap(n1,n2);
119     }
120     printf("%d %d
",n1,n2);
121     for(int i=1;i<=n1;i++) printf("%d ",c[x[i]]);
122     printf("
");
123     for(int i=1;i<=n2;i++) printf("%d ",c[y[i]]);
124      return 0;
125 }

 

以上是关于EOJ3652乘法还原(二分图)的主要内容,如果未能解决你的问题,请参考以下文章

EOJ Monthly 2019.2 E. 中位数 (二分+dfs)

EOJ3654管理孩子(贪心,二分答案)

EOJ Monthly 2020.3 A.迷宫 (二分+最大流)

EOJ Monthly 2019.2 E 中位数 (二分+中位数+dag上dp)

BZOJ 2738 矩阵乘法(整体二分+二维树状数组)

完全二分图生成树计数