[破碎的状态] 一道Flag网络流
题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=312468
感谢@zhaoxinyi 提供解题思路
感谢@似水流年 提供翻译
题意:
给你n对数字,每一对你可以算出它们的和/差/积
但是你要保证n对的结果不同,求一种构造方案
这一题我立下flag:AC了再去吃饭
然后17:50给过了才去吃饭..饿死了..所以叫做flag网络流
这一题建个网络流即可,s-->每一个数字-->每个方案-->每对数字-->t,然后直接看流量出解
代码:
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=99999999;
struct edge
{
int y;
int weight;
edge * next;
edge * anti;
};
edge * li[100005];
int top=0;
edge * new_edge()
{
static edge a[500005];
return &a[top++];
}
edge * inserts(int x,int y,int w)
{
edge * t=new_edge();
t->y=y;
t->weight=w;
t->next=li[x];
li[x]=t;
return t;
}
void insert_edge(int x,int y,int w)
{
edge * t1=inserts(x,y,w);
edge * t2=inserts(y,x,0);
t1->anti=t2;
t2->anti=t1;
}
int dist[100005];
int bfs(int s,int t)
{
static int que[100005];
int front=0,rail=1;
memset(dist,-1,sizeof(dist));
dist[s]=0;
que[0]=s;
for (;front<rail;front++)
{
int now=que[front];
edge * x;
for (x=li[now];x!=0;x=x->next)
{
if ((dist[x->y]==-1)&&(x->weight>0))
{
dist[x->y]=dist[now]+1;
if (x->y==t) return 1;
que[rail++]=x->y;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
int tot=0;
int pre[100005];
edge * cur[100005];
edge * path[100005];
for (;bfs(s,t);)
{
int now=s;
memcpy(cur,li,sizeof(cur));
for (;dist[s]!=-1;)
{
if (now==t)
{
int temp;
temp=now;
int mini=inf;
for (;temp!=s;temp=pre[temp])
{
mini=min(mini,path[temp]->weight);
}
tot+=mini;
temp=now;
for (;temp!=s;temp=pre[temp])
{
path[temp]->weight-=mini;
path[temp]->anti->weight+=mini;
}
now=s;
}
edge * x;
for (x=cur[now];x!=0;x=x->next)
{
if ((dist[x->y]==dist[now]+1)&&(x->weight>0))
{
pre[x->y]=now;
path[x->y]=x;
cur[now]=x;
now=x->y;
break;
}
}
if (x==0)
{
dist[now]=-1;
now=pre[now];
}
}
}
return tot;
}
map<long long,int> ma;
int count_sum=0;
void get_try(long long x)
{
if (ma.find(x)==ma.end())
{
ma[x]=count_sum++;
}
}
int a[2505],b[2505];
int main()
{
#ifdef absi2011
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
for (;;)
{
int n;
count_sum=0;
memset(li,0,sizeof(li));
top=0;
if (scanf("%d",&n)==-1) break;
int i;
ma.erase(ma.begin(),ma.end());
for (i=0;i<n;i++)
{
scanf("%d%d",&a[i],&b[i]);
get_try((long long)a[i]+b[i]);
get_try((long long)a[i]-b[i]);
get_try((long long)a[i]*b[i]);
}
int s=count_sum+4*n;
int t=s+1;
for (i=0;i<count_sum;i++)
{
insert_edge(s,i,1);
}
for (i=0;i<n;i++)
{
insert_edge(ma[(long long)a[i]+b[i]],count_sum+i*3,1);
insert_edge(ma[(long long)a[i]-b[i]],count_sum+i*3+1,1);
insert_edge(ma[(long long)a[i]*b[i]],count_sum+i*3+2,1);
insert_edge(count_sum+i*3,count_sum+n*3+i,1);
insert_edge(count_sum+i*3+1,count_sum+n*3+i,1);
insert_edge(count_sum+i*3+2,count_sum+n*3+i,1);
insert_edge(count_sum+n*3+i,t,1);
}
if (max_flow(s,t)<n)
{
printf("impossible\n");
continue;
}
for (i=0;i<n;i++)
{
edge * x;
for (x=li[count_sum+n*3+i];x!=0;x=x->next)
{
int t=x->y-count_sum-i*3;
if ((t>=0)&&(t<=2))
{
if (x->weight!=0)
{
if (t==0)
{
printf("%d + %d = %d\n",a[i],b[i],a[i]+b[i]);
}
else if (t==1)
{
printf("%d - %d = %d\n",a[i],b[i],a[i]-b[i]);
}
else
{
printf("%d * %d = ",a[i],b[i]);
cout<<(long long)a[i]*b[i]<<'\n';
}
}
}
}
}
}
return 0;
}
评论 (0)