

根据时间向图中加边,将每个点都拆成每一天时的情况,当天可以向下一天滞留无限的人,每一天的起点和终点都分别与源汇连容量为正无穷的边,当最大流大于等于人数时就输出,无解用并查集维护即可。当前弧优化真的快好多。
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=5001,inf=2147483647;
int fa[15],h[501],r[501],a[9000][4],first[maxn],cur[maxn],nxt[maxn*100],to[maxn*100],w[maxn*100],dis[maxn];
int n,m,k,tot=0,s=4999,t=5000,cnt=0,flow=0;
int read()
{
char ch=getchar();
int flag=1,x=0;
while((ch<'0'||ch>'9')&&ch!='-')
ch=getchar();
if(ch=='-')
{
flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*flag;
}
int find(int x)
{
if(x==fa[x])
return x;
return fa[x]=find(fa[x]);
}
void add(int x,int y,int wi)
{
nxt[cnt]=first[x];
first[x]=cnt;
to[cnt]=y;
w[cnt]=wi;
cnt++;
}
bool bfs()
{
memset(dis,0x3f,sizeof(dis));
queue<int>q;
dis[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
int i;
for(i=first[u];i!=-1;i=nxt[i])
{
if(w[i]&&dis[u]+1<dis[to[i]])
{
dis[to[i]]=dis[u]+1;
q.push(to[i]);
}
}
}
if(dis[t]==dis[4998])
return 0;
return 1;
}
int dfs(int x,int flow)
{
if(x==t)
return flow;
for(int &i=cur[x];i!=-1;i=nxt[i])
{
if(w[i]&&dis[to[i]]==dis[x]+1)
{
int temp=dfs(to[i],(int)min(flow,w[i]));
if(temp)
{
w[i]-=temp;
w[i^1]+=temp;
return temp;
}
}
}
return 0;
}
int dinic(int x)
{
int i;
for(i=0;i<=14;i++)
{
add(x*15+i,(x+1)*15+i,inf);
add((x+1)*15+i,x*15+i,0);
}
for(i=1;i<=tot;i++)
{
if(a[i][3]==x%r[a[i][2]])
{
add(x*15+a[i][0],(x+1)*15+a[i][1],h[a[i][2]]);
add((x+1)*15+a[i][1],x*15+a[i][0],0);
}
}
add(s,x*15,inf);
add(x*15,s,0);
add(x*15+14,t,inf);
add(t,x*15+14,0);
while(bfs())
{
for(i=0;i<=5000;i++)
cur[i]=first[i];
int temp;
while(temp=dfs(s,inf))
flow+=temp;
}
return flow;//总共
}
int main()
{
memset(first,-1,sizeof(first));
n=read(),m=read(),k=read();
int i;
for(i=0;i<=14;i++)
fa[i]=i;
for(i=1;i<=m;i++)
{
h[i]=read(),r[i]=read();
int j,la,lat,now;
for(j=0;j<r[i];j++)
{
if(j==0)
{
la=read();
if(la==-1)
la=14;
lat=la;
}
else
{
now=read();
if(now==-1)
now=14;
int fx=find(la),fy=find(now);
if(fx!=fy)
fa[fy]=fx;
a[++tot][0]=la,a[tot][1]=now,a[tot][2]=i,a[tot][3]=j-1;
la=now;
if(j==r[i]-1)
a[++tot][0]=now,a[tot][1]=lat,a[tot][2]=i,a[tot][3]=j;
}
}
}
int fx=find(0),fy=find(14);
if(fx!=fy)
{
printf("somebodysetupusthebomb\n");
fclose(stdin);
fclose(stdout);
return 0;
}
int ans=0;
while(true)
{
if(dinic(ans)>=k)
{
printf("%d\n",ans);
break;
}
ans++;
}
return 0;
}
浙公网安备 33010602011771号