终于过了,发篇题解庆祝一下
其实主要是因为被卡死了最后一个点来……
普度众生?
不存在的!只是想给大家JIO一下当前弧优化
如果大佬已经了解就请跳过蒟蒻的题解吧
这一题的建边并不难,SS向单位建一个流量为R_iRi的边,每个单位向每个桌子建一条流量为1的边,桌子向TT建一条流量为C_iCi的边就好啦
步入正题:
我们想一下,
如果有一个点出去了很多条边,那么在DFS中会有重复的遍历
出题人恶良心一点就会被卡的死死的
如何不被卡死!这是一个问题QAQ
不要跟我说卡常,我卡了半天也没卡进去
所以我们可以在分完层之后,跑完一次后就记录一下上一次跑的边
然后就可以优秀的跑过了
其实当前弧优化要修改的地方真的不多
上代码QAQ:
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; int head[100005],num_edge=-1,n,m,s,t,tot; struct Edge { int next,to,dis; }edge[100005]; void add(int from,int to,int dis) { edge[++num_edge].next=head[from]; edge[num_edge].to=to; edge[num_edge].dis=dis; head[from]=num_edge; } int d[10001],q[10001],cur[10001]; bool bfs() { int hea=0,tai=1; memset(d,0,sizeof(d)); d[s]=1; q[1]=s; do { hea++; int x=q[hea]; for(register int i=head[x];i!=-1;i=edge[i].next) { int y=edge[i].to; if(!d[y]&&edge[i].dis>0) { d[y]=d[x]+1; q[++tai]=y; } } }while(hea<tai); if(!d[t]) return 0; else return 1; } int dfs(int pos,int last) { if(pos==t) return last; for(register int i=cur[pos];i!=-1;i=edge[i].next)//当前弧优化QAQ if(d[edge[i].to]==d[pos]+1&&edge[i].dis) { int data=dfs(edge[i].to,min(edge[i].dis,last)); if(data>0) { edge[i].dis-=data; edge[i^1].dis+=data; if(edge[i].dis) cur[pos]=i;//当前弧优化QAQ return data; } } return 0; } inline int read() { char ch='!';int z=1,num=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')z=-1,ch=getchar(); while(ch<='9'&&ch>='0')num=(num<<3)+(num<<1)+ch-'0',ch=getchar(); return z*num; } inline int Dinic() { int ans=0; while(bfs()) { memcpy(cur,head,sizeof(cur));//当前弧优化QAQ while(int data=dfs(s,0x3f3f3f3f)) ans+=data; } return ans; } int main(){ memset(head,-1,sizeof(head)); n=read(); m=read(); s=0; t=n+m+1; for(register int i=1;i<=n;++i) { int r; r=read(); add(s,i,r); add(i,s,0); tot+=r; } for(register int i=1;i<=n;++i) for(register int j=1;j<=m;++j) add(i,j+n,1),add(j+n,i,0); for(register int i=1;i<=m;++i) { int c; c=read(); add(i+n,t,c); add(t,i+n,0); } int maxflow=Dinic(); if(maxflow!=tot){printf("0");return 0;} printf("1 "); for(register int i=1;i<=n;++i) { for(register int j=head[i];j;j=edge[j].next) if(edge[j].dis==0&&edge[j].to!=0) printf("%d ",edge[j].to-n); printf(" "); } }