我大构造题岂能与区区二分图匹配为伍?
有意思的一道题。
首先,我们可以知道一对数如果是要有用的,它必然会产生至少一个数到
其次,题目中说了,顺序是不重要的,我们的目的只是让构造出的数对所产生的数和序列中可以一一对应即可。
考虑为了让数尽可能地小于等于
继续观察性质。
注意到
那么我们就自然地想到把
输出方案就匹配点
时间复杂度取决于你是用啥跑的二分图最大匹配,笔者用的网络流,故复杂度最坏
参考代码:
#include<bits/stdc++.h>
#define ll long long
#define INF 214748364719260817ll
using namespace std;
ll n,m;
ll in[2005],b[1005];
map<ll,ll>sum;
bool cmp(ll a,ll b)
{
return a>b;
}
struct ed
{
ll v,w,next;
}edge[8010005];
ll head[2005],cnt=1;
void add(ll u,ll v,ll w)
{
edge[++cnt].v=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt;
edge[++cnt].v=u;edge[cnt].next=head[v];head[v]=cnt;
}
ll t;
ll dep[2005],cur[2005];
queue<ll>k;
bool bfs()
{
cur[0]=head[0];
for(ll i=1;i<=t;++i)dep[i]=0,cur[i]=head[i];
dep[0]=1;
k.push(0);
while(!k.empty())
{
ll id=k.front();k.pop();
for(ll i=head[id];i;i=edge[i].next)
{
ll v=edge[i].v,w=edge[i].w;
if(!w||dep[v])continue;
dep[v]=dep[id]+1;
k.push(v);
}
}
return dep[t];
}
ll dfs(ll id,ll get)
{
if(id==t)return get;
ll use=0;
for(ll i=cur[id];i;i=edge[i].next)
{
cur[id]=i;
ll v=edge[i].v,w=edge[i].w;
if(!w||dep[v]!=dep[id]+1)continue;
ll nu=dfs(v,min(get,w));
edge[i].w-=nu;
edge[i^1].w+=nu;
get-=nu;use+=nu;
if(!nu)dep[v]=0;
if(!get)return use;
}
if(!use)dep[id]=0;
return use;
}
struct px
{
ll a,b;
}ans[2005];
ll tot;
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>m;
for(ll i=1;i<=n;++i)cin>>in[i],b[i]=in[i],++sum[in[i]];
sort(b+1,b+1+n);
ll cot=unique(b+1,b+1+n)-b-1;
sort(b+1,b+1+cot,cmp);
ll ls=0,rs=0,ns=0;
for(ll i=1;i<=cot;++i)
{
if(b[i]<=m/3)break;
++ls;
add(0,ls,sum[b[i]]);
ns+=sum[b[i]];
for(ll j=i+1;j<=cot;++j)
if(b[i]*2+b[j]<=m&&b[i]%b[j]==0)
add(i,j,INF);
}
t=cot+1;
for(ll i=ls+1;i<=cot;++i)add(i,t,sum[b[i]]);
ll lls,res=0;
while(bfs())
while(lls=dfs(0,INF))res+=lls;
if(res!=ns)cout<<-1;
else
{
for(ll i=1;i<=ls;++i)
for(ll j=head[i];j;j=edge[j].next)
{
ll v=edge[j].v;
if(v)
{
for(ll k=1;k<=edge[j^1].w;++k)ans[++tot].a=b[i]*2+b[v],ans[tot].b=b[i]+b[v];
}
}
for(ll i=ls+1;i<=cot;++i)
for(ll j=head[i];j;j=edge[j].next)
{
ll v=edge[j].v;
if(v==t)
for(ll k=1;k<=edge[j].w;++k)ans[++tot].a=b[i]*3,ans[tot].b=2*b[i];
}
cout<<tot<<'\n';
for(ll i=1;i<=tot;++i)cout<<ans[i].a<<' '<<ans[i].b<<'\n';
}
}