题目链接:
https://odzkskevi.qnssl.com/19afdbfcc9ee8720dd81032e85ed2a5a?v=1506446502
题解:
二分匹配或网络流。
代码:
Dinic模板:
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
typedef long long ll;
const ll MAX_E=2500+10;//edge
const ll MAX_P=2500+10;//point
struct node
{
ll to,next,w;
}edge[MAX_E*MAX_E];
ll head[MAX_P*10],cur[MAX_P*10];
ll a[MAX_P*10],b[MAX_P*10];
ll pos[MAX_P*10][3];
ll dis[MAX_P*10];
ll w[MAX_P*10];
ll top;
ll s,t;
void init()
{
top=1;
met(head,-1);
met(cur,-1);
}
void Add(ll u,ll v,ll w)
{
edge[++top].to=v;
edge[top].w=w;
edge[top].next=head[u];
head[u]=top;
}
void Add_edge(ll u,ll v,ll w)
{
Add(u,v,w);
Add(v,u,0);
}
ll bfs()
{
queue<ll>q;
met(dis,0);
while(!q.empty())
q.pop();
dis[s]=1;
q.push(s);
while(!q.empty())
{
ll x=q.front();
q.pop();
for(ll i=head[x];i!=-1;i=edge[i].next)
{
ll y=edge[i].to;
if(!dis[y]&&edge[i].w)
{
dis[y]=dis[x]+1;
q.push(y);
}
}
}
return dis[t];
}
ll dfs(ll x,ll flow)
{
if(x==t||flow==0)
return flow;
ll ans=0;
for(ll &i=cur[x];i!=-1;i=edge[i].next)
// for(ll i=head[x];i!=-1;i=edge[i].next)
{
ll y=edge[i].to;
if(dis[y]==dis[x]+1&&edge[i].w)
{
ll a=dfs(y,min(edge[i].w,flow-ans));
edge[i].w-=a;
edge[i^1].w+=a;
ans+=a;
if(flow==ans)
break;
}
}
return ans;
}
ll Dinic()
{
ll ans=0;
while(bfs())
{
memcpy(cur,head,sizeof(head));
ll temp=dfs(s,inf);
// while(ll temp=dfs(s,inf))
ans+=temp;
}
return ans;
}
int main()
{
ll n;
while(scanf("%lld",&n)!=EOF)
{
met(a,0);met(b,0);
met(pos,0);met(w,0);
for(ll i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i],&b[i]);
w[i*3-2]=a[i]+b[i];
w[i*3-1]=a[i]-b[i];
w[i*3]=a[i]*b[i];
}
sort(w+1,w+1+n*3);
ll len=unique(w+1,w+1+n*3)-w-1;
s=0,t=n+len+1;
init();
for(ll i=1;i<=n;i++)
{
Add_edge(s,i,1);
ll x=lower_bound(w+1,w+len+1,a[i]+b[i])-w;
Add_edge(i,x+n,1);
pos[i][0]=top;
x=lower_bound(w+1,w+len+1,a[i]-b[i])-w;
Add_edge(i,x+n,1);
pos[i][1]=top;
x=lower_bound(w+1,w+len+1,a[i]*b[i])-w;
Add_edge(i,x+n,1);
pos[i][2]=top;
}
for(ll i=1;i<=len;i++)
Add_edge(i+n,t,1);
ll ans=Dinic();
if(ans<n)
printf("impossible\n");
else
{
for(ll i=1;i<=n;i++)
{
if (edge[pos[i][0]].w)
printf("%lld + %lld = %lld\n",a[i],b[i],a[i]+b[i]);
else if (edge[pos[i][1]].w)
printf("%lld - %lld = %lld\n",a[i],b[i],a[i]-b[i]);
else
printf("%lld * %lld = %lld\n",a[i],b[i],a[i]*b[i]);
}
}
}
}