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)
EOJ Monthly 2020.3 A.迷宫 (二分+最大流)