题目链接:https://vjudge.net/contest/298079#problem/J
解题思路:
将整个过程分成n个步骤,那么在每个步骤中都有一个新的队列,它是空的,现在要加入当前步骤的a[i],但是还有考虑上一个步骤是否队列中还存在数据没有被传送,所以我们需要从上一个步骤连一条边指向下一个步骤,把它加到a[i]中一起处理。还有每一个步骤都有一个d可以将数据流出,所以我们一个可以分割成n*(s+q) + n个点,然后去跑最大流。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int dx[4] = {1,0,0,-1};
const int dy[4] = {0,1,-1,0};
const int mx = 1e4 + 10;
int n,m,S,T,tot,head[mx],cur[mx],s;
int du[mx],c[mx];
int a[mx],q;
bool vis[mx];
struct node
{
int v,f;
int nxt;
}e[mx*10];
void add(int u,int v,int f)
{
e[tot] = {v,f,head[u]};
head[u] = tot++;
e[tot] = {u,0,head[v]};
head[v] = tot++;
}
int dep[mx];
bool bfs()
{
memset(dep,0,sizeof(dep));
queue<int> que;
que.push(S);
dep[S] = 1;
while(!que.empty())
{
int no = que.front();
que.pop();
for(int i=head[no];~i;i=e[i].nxt)
{
int v = e[i].v;
if(e[i].f&&!dep[v]){
dep[v] = dep[no] + 1;
que.push(v);
}
}
}
return dep[T];
}
int dfs(int u,int flow)
{
if(u==T || !flow) return flow;
int used = 0;
for(int i=head[u];~i;i=e[i].nxt)
{
int v = e[i].v;
if(dep[u]+1==dep[v]){
int w = dfs(v,min(flow-used,e[i].f));
e[i].f -= w;
e[i^1].f += w;
used += w;
if(used==flow) return flow;
}
}
if(!used) dep[u] = 0;
return used;
}
int maxflow()
{
int ans = 0;
while(bfs()){
// copy(head,head+mx,cur);
ans += dfs(S,inf);
}
return ans;
}
int getid(int i,int j,int w)
{
if(w) return i*(s+q) + s + j;
return i*(s+q) + j;
}
int main()
{
scanf("%d%d%d",&n,&q,&s);
int v,cnt = n*(s+q),d;
ll sum = 0;
for(int i=1;i<=s;i++){
scanf("%d",du+i);
}
memset(head,-1,sizeof(head));
S = 0,T = cnt + n + 1;
for(int i=1;i<=q;i++) scanf("%d",c+i);
for(int i=0;i<n;i++){
scanf("%d",&d);
for(int j=1;j<=q;j++) vis[j] = 0;
for(int j=1;j<=s;j++){
scanf("%d",&v);
sum += v;
int ids = getid(i,j,0);
int idq = getid(i,du[j],1);
add(S,ids,v);
add(ids,idq,inf);
if(!vis[du[j]]){
add(idq,cnt+i+1,c[du[j]]);
if(i!=n-1) add(cnt+i+1,getid(i+1,j,0),inf);
vis[du[j]] = 1;
}
}
add(cnt+i+1,T,d);
}
if(sum==maxflow()) puts("possible");
else puts("impossible");
return 0;
}