Description
现在有 个重量分别为 的物品需要吊到楼上,有 个吊车,第 个吊车的重量为 ,可以吊起的重量为 ,重量为 表示该吊车可以无代价的先放置在楼上以吊起重物或其他吊车,问如果安排吊车可以把这 个重物都吊到楼上,一个吊车只能用一次
Input
第一行一整数
表示吊车数量,之后
行每行两个整数
表示第
个吊车可吊起的重量和自身的重量,之后输入一整数
表示要吊起的重物数,最后
个整数
表示第
个重物的重量
Output
如果存在合法方案则输出 行,第 行一个吊车编号序列 表示 吊车可以直接放置在楼上,且第 个吊车可以吊起第 个吊车, ,且第 个吊车可以吊起 重物,否则输出
Sample Input
5
0 1
1 2
2 3
3 4
0 2
2
4 2
Sample Output
5 3 4
1 2
Solution
网络流, 个吊车看作两排 个点,拆点保证每个吊车至多用一次, 个重物看作 个点,建图如下:
1.源点向所有自身重量为 的吊车连容量为 的边表示这些吊车可以无代价放置在楼上
2.每个吊车拆成的第一个点向第二个点连容量为 的边来限流
3.如果 ,即第 个吊车可以吊起第 个吊车,则从第 个吊车拆成的第二个点向第 个吊车拆成的第一个点连容量为 的边
4.如果 ,即第 个吊车可以吊起第 个重物,则从第 个吊车拆成的第二个点向第 个重物连容量为 的边
5.每个重物向汇点连容量为 的边,用最大流是否为 来判断是否所有的重物都可以被吊起
在最大流解决了方案的存在性之后,对整张网络的前向弧构成的图 ,只走流量流完的边,来找到第 个重物是通过哪些吊车依次吊起的
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
#define maxn 500
#define maxm 50000
#define INF 0x3f3f3f3f
int head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no;//s为源点,e为汇点,n为点数,no为边数
struct point
{
int u,v,flow,next;
point(){};
point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){};
}p[maxm];
void add(int x,int y,int z)//从x到y建容量为z的边
{
p[no]=point(x,y,head[x],z);//前向弧,标号为偶
head[x]=no++;
p[no]=point(y,x,head[y],0);//后向弧,标号为奇
head[y]=no++;
}
void init()//初始化
{
memset(head,-1,sizeof(head));
no=0;
}
bool bfs()
{
int i,x,y;
queue<int>q;
memset(d,-1,sizeof(d));
d[s]=0;
q.push(s);
while(!q.empty())
{
x=q.front();
q.pop();
for(i=head[x];i!=-1;i=p[i].next)
{
if(p[i].flow&& d[y=p[i].v]<0)
{
d[y]=d[x]+1;
if(y==e)
return true;
q.push(y);
}
}
}
return false;
}
int dinic()//最大流
{
int i,loc,top,x=s,nowflow,maxflow=0;
while(bfs())
{
memcpy(cur,head,sizeof(head));
top=0;
while(true)
{
if(x==e)
{
nowflow=INF;
for(i=0;i<top;i++)
{
if(nowflow>p[st[i]].flow)
{
nowflow=p[st[i]].flow;
loc=i;
}
}
for(i=0;i<top;i++)
{
p[st[i]].flow-=nowflow;
p[st[i]^1].flow+=nowflow;
}
maxflow+=nowflow;
top=loc;
x=p[st[top]].u;
}
for(i=cur[x];i!=-1;i=p[i].next)
if(p[i].flow&&d[p[i].v]==d[x]+1)
break;
cur[x]=i;
if(i!=-1)
{
st[top++]=i;
x=p[i].v;
}
else
{
if(!top)
break;
d[x]=-1;
x=p[st[--top]].u;
}
}
}
return maxflow;
}
int n,m,W[maxn],L[maxn],T[maxn],vis[maxn],tar;
vector<int>ans[maxn],vec;
void dfs(int u)
{
if(u>2*n)tar=u;
if(tar)return ;
vec.push_back(u);
vis[u]=1;
for(int i=head[u];~i;i=p[i].next)
{
int v=p[i].v,flow=p[i].flow;
if(i%2==0&&!vis[v]&&!flow)
{
dfs(v);
break;
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&W[i],&L[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d",&T[i]);
init();
s=0;
e=2*n+m+1;
for(int i=1;i<=n;i++)
{
if(W[i]==0)add(s,i,1);
add(i,n+i,1);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&L[i]>=W[j])
add(n+i,j,1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(L[i]>=T[j])
add(n+i,2*n+j,1);
for(int i=1;i<=m;i++)add(2*n+i,e,1);
if(dinic()==m)
{
memset(vis,0,sizeof(vis));
for(int i=head[s];~i;i=p[i].next)
{
int v=p[i].v,flow=p[i].flow;
if(!vis[v]&&!flow)
{
tar=0;
vec.clear();
dfs(v);
for(int i=0;i<vec.size();i+=2)ans[tar-2*n].push_back(vec[i]);
}
}
for(int i=1;i<=m;i++)
for(int j=0;j<ans[i].size();j++)
printf("%d%c",ans[i][j],j==ans[i].size()-1?'\n':' ');
}
else printf("impossible\n");
}