[CTSC1999]家园
这道题让我懂得了一个全新的建图方法。。。当我们跑网络流或者费用流的时候。。。如果不能通过建图一边跑完怎么办。。。答案很简单就是跑多变。。。哈哈哈
这里要用到一个Asia不知道从哪里学来的定义叫拆门。。。就是一个题,我可能有很多的子任务,但是他们不能通过直接建立一个图解决。。。
那么我们就可以这样思考(前提是这道题是网络流),他们有什么联系,我们可以通过这些联系建立一个大图,使每个子任务合起来,最后在动态中不断尽行求取就可以了。。。
这道题就是,分别和每一天的地球和月球连inf的边(貌似这玩意可以叫拆门?),然后如果不是第一天,就把上一天的空间站向这一天的连一条inf表示可能有人留在这里。最后把上一天的运输船的位置向这一天的连一条运输船人数的边。
代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 10001
#define re register
#define inf k
// emm。。。这个东西无所谓。。。
// 只要 >=k 就可以了。。。
using namespace std;
int num=-1,head[maxn],w[maxn],dep[maxn],s,t,cur[maxn];
int p[maxn],hp[maxn],a[651][651],sum,n,m,k,tot;
struct asd{
int next;
int to;
} e[maxn<<2];
queue <int> q;
void add(int x,int y,int z)
{
e[++num].next=head[x];
e[num].to=y;
w[num]=z;
head[x]=num;
}
bool bfs()
{
while(!q.empty()) q.pop();
memset(dep,0,sizeof(dep));
dep[s]=1; q.push(s);
while(!q.empty())
{
int now=q.front(); q.pop();
for(int i=head[now];i!=-1;i=e[i].next)
if(w[i]>0 && dep[e[i].to]==0)
{
dep[e[i].to]=dep[now]+1;
q.push(e[i].to);
}
}
if(dep[t]==0) return 0;
else return 1;
}
int dfs(int u,int dis)
{
if(u==t) return dis;
int diss=0;
for(int i=head[u];i!=-1;i=e[i].next)
if(w[i]!=0 && dep[e[i].to]==dep[u]+1)
{
int disss=dfs(e[i].to,min(dis,w[i]));
if(disss)
{
diss+=disss;
dis-=disss;
w[i]-=disss;
w[i^1]+=disss;
if(!dis) break;
}
}
return diss;
}
int Dinic()
{
int ans=0;
while(bfs())
{
for(int i=0;i<=t;i++)
cur[i]=head[i];
while(int d=dfs(s,inf))
ans+=d;
}
return ans;
}
int main()
{
memset(head,-1,sizeof(head));
cin>>n>>m>>k;
n+=2;
s=0; t=1001;
for(re int i=1;i<=m;i++)
{
scanf("%d%d",&p[i],&hp[i]);
for(re int j=0,x;j<hp[i];j++)
{
scanf("%d",&x);
a[i][j]=x;
a[i][j]+=2;
}
}
int ans=0;
while(ans<30)
{
add(ans*n+1,t,inf);
add(t,ans*n+1,0);
add(s,ans*n+2,inf);
add(ans*n+2,s,0);
if(ans!=0)
{
for(re int i=1;i<=n;i++)
{
add((ans-1)*n+i,ans*n+i,inf);
add(ans*n+i,(ans-1)*n+i,0);
}
for(re int i=1;i<=m;i++)
{
int x=a[i][(ans-1)%hp[i]];
int y=a[i][ans%hp[i]];
add((ans-1)*n+x,ans*n+y,p[i]);
add(ans*n+y,(ans-1)*n+x,0);
}
}
sum+=Dinic();
if(sum>=k) break;
ans++;
}
cout<<((ans<30) ? ans:0);
}