http://acm.hdu.edu.cn/showproblem.php?pid=4292
题解:网络流模板题
之前用的dinic模板加弧优化(不优化TLE)不如kuangbin模板快,网上找了另一个dinic不用队列快的更多
代码:
kuangbin
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1000;//点数的最大值
const int MAXM=1000500;//边数的最大值
struct Node
{
int from,to,next;
int cap;
}edge[MAXM];
int tol;
int dep[MAXN];//dep为点的层次
int head[MAXN];
int n;
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)//第一条变下标必须为偶数
{
edge[tol].from=u;
edge[tol].to=v;
edge[tol].cap=w;
edge[tol].next=head[u];
head[u]=tol++;
edge[tol].from=v;
edge[tol].to=u;
edge[tol].cap=0;
edge[tol].next=head[v];
head[v]=tol++;
}
int BFS(int start,int end)
{
int que[MAXN];
int front,rear;
front=rear=0;
memset(dep,-1,sizeof(dep));
que[rear++]=start;
dep[start]=0;
while(front!=rear)
{
int u=que[front++];
if(front==MAXN)front=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>0&&dep[v]==-1)
{
dep[v]=dep[u]+1;
que[rear++]=v;
if(rear>=MAXN)rear=0;
if(v==end)return 1;
}
}
}
return 0;
}
int dinic(int start,int end)
{
int res=0;
int top;
int stack[MAXN];//stack为栈,存储当前增广路
int cur[MAXN];//存储当前点的后继
while(BFS(start,end))
{
memcpy(cur,head,sizeof(head));
int u=start;
top=0;
while(1)
{
if(u==end)
{
int min=INF;
int loc;
for(int i=0;i<top;i++)
if(min>edge[stack[i]].cap)
{
min=edge[stack[i]].cap;
loc=i;
}
for(int i=0;i<top;i++)
{
edge[stack[i]].cap-=min;
edge[stack[i]^1].cap+=min;
}
res+=min;
top=loc;
u=edge[stack[top]].from;
}
for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
break;
if(cur[u]!=-1)
{
stack[top++]=cur[u];
u=edge[cur[u]].to;
}
else
{
if(top==0)break;
dep[u]=-1;
u=edge[stack[--top]].from;
}
}
}
return res;
}
int food[MAXN],drink[MAXM];
char ch;
int main()
{
int nn,f,d;
int i,j;
while(~scanf("%d%d%d",&nn,&f,&d)){
n=2*nn+f+d+2;
init();
for(i=1;i<=f;i++)scanf("%d",&food[i]);
for(i=1;i<=d;i++)scanf("%d",&drink[i]);
getchar();
for(i=1;i<=nn;i++){
for(j=1;j<=f;j++){
scanf("%c",&ch);
if(ch=='Y'){
addedge(j,f+i,1);
}
}
getchar();
}
for(i=1;i<=nn;i++){
for(j=1;j<=d;j++){
scanf("%c",&ch);
if(ch=='Y')addedge(f+nn+i,2*nn+f+j,1);
}
getchar();
}
for(i=1;i<=nn;i++)addedge(f+i,nn+f+i,1);
for(i=1;i<=f;i++)addedge(2*nn+f+d+1,i,food[i]);
for(i=1;i<=d;i++)addedge(2*nn+f+i,2*nn+f+d+2,drink[i]);
printf("%d\n",dinic(2*nn+f+d+1,2*nn+f+d+2));
}
// cout << "Hello world!" << endl;
return 0;
}
原模版
#include <iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxN=1000;
const int maxM=1000000;
const int inf=0x3f3f3f3f;
class Graph
{
private:
int cnt;
int Head[maxN];
int Next[maxM];
int W[maxM];
int V[maxM];
int Depth[maxN];
int cur[maxN];//cur就是记录当前点u循环到了哪一条边
public:
int s,t,n;
void init(int nn,int ss,int tt)//初始化
{
n=nn;
s=ss;
t=tt;
cnt=-1;
memset(Head,-1,sizeof(Head));
memset(Next,-1,sizeof(Next));
return;
}
void _Add(int u,int v,int w)
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
V[cnt]=v;
W[cnt]=w;
}
void Add_Edge(int u,int v,int w)
{
_Add(u,v,w);
_Add(v,u,0);
}
int dfs(int u,int flow)
{
if (u==t)
return flow;
for (int& i=cur[u];i!=-1;i=Next[i])//注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
{
if ((Depth[V[i]]==Depth[u]+1)&&(W[i]!=0))
{
int di=dfs(V[i],min(flow,W[i]));
if (di>0)
{
W[i]-=di;
W[i^1]+=di;
return di;
}
}
}
return 0;
}
int bfs()
{
queue<int> Q;
while (!Q.empty())
Q.pop();
memset(Depth,0,sizeof(Depth));
Depth[s]=1;
Q.push(s);
do
{
int u=Q.front();
Q.pop();
for (int i=Head[u];i!=-1;i=Next[i])
if ((Depth[V[i]]==0)&&(W[i]>0))
{
Depth[V[i]]=Depth[u]+1;
Q.push(V[i]);
}
}
while (!Q.empty());
if (Depth[t]>0)
return 1;
return 0;
}
int Dinic()
{
int Ans=0;
while (bfs())
{
for (int i=1;i<=n;i++)//每一次建立完分层图后都要把cur置为每一个点的第一条边 感谢@青衫白叙指出这里之前的一个疏漏
cur[i]=Head[i];
while (int d=dfs(s,inf))
{
Ans+=d;
}
}
return Ans;
}
};
int food[maxN],drink[maxN];
char ch;
int main()
{
int n,f,d;
int i,j;
Graph G;
while(~scanf("%d%d%d",&n,&f,&d)){
G.init(2*n+f+d+2,2*n+f+d+1,2*n+f+d+2);
for(i=1;i<=f;i++)scanf("%d",&food[i]);
for(i=1;i<=d;i++)scanf("%d",&drink[i]);
getchar();
for(i=1;i<=n;i++){
for(j=1;j<=f;j++){
scanf("%c",&ch);
if(ch=='Y'){
G.Add_Edge(j,f+i,1);
}
}
getchar();
}
for(i=1;i<=n;i++){
for(j=1;j<=d;j++){
scanf("%c",&ch);
if(ch=='Y')G.Add_Edge(f+n+i,2*n+f+j,1);
}
getchar();
}
for(i=1;i<=n;i++)G.Add_Edge(f+i,n+f+i,1);
for(i=1;i<=f;i++)G.Add_Edge(2*n+f+d+1,i,food[i]);
for(i=1;i<=d;i++)G.Add_Edge(2*n+f+i,2*n+f+d+2,drink[i]);
printf("%d\n",G.Dinic());
}
// cout << "Hello world!" << endl;
return 0;
}
最快的
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=1<<30;
const int nMax=100105;
const int mMax=3000005;
struct Node
{
int c,u,v,next;
void insert(int nu,int nv,int nc,int nnext)
{
u=nu;
v=nv;
c=nc;
next=nnext;
}
}edge[mMax];
int ne,head[nMax];
int cur[nMax],ps[nMax],dep[nMax];
void addedge(int u,int v,int w) //加边
{
edge[ne].insert(u,v,w,head[u]);
head[u]=ne++;
edge[ne].insert(v,u,0,head[v]);
head[v]=ne++;
}
int dinic(int s, int t){ // dinic
int tr, res = 0;
int i, j, k, f, r, top;
while(1){
memset(dep, -1, sizeof(dep));
for(f = dep[ps[0]=s] = 0, r = 1; f != r;)
{
for(i = ps[f ++], j = head[i]; j; j = edge[j].next)
{
if(edge[j].c && dep[k=edge[j].v] == -1)
{
dep[k] = dep[i] + 1;
ps[r ++] = k;
if(k == t)
{
f = r; break;
}
}
}
}
if(dep[t] == -1) break;
memcpy(cur, head, sizeof(cur));
i = s, top = 0;
while(1)
{
if(i == t)
{
for(tr =inf, k = 0; k < top; k ++)
{
if(edge[ps[k]].c < tr)
{
tr = edge[ps[f=k]].c;
}
}
for(k = 0; k < top; k ++)
{
edge[ps[k]].c -= tr;
edge[ps[k]^1].c += tr;
}
i = edge[ps[top=f]].u;
res += tr;
}
for(j = cur[i]; cur[i]; j = cur[i] =edge[cur[i]].next)
{
if(edge[j].c && dep[i]+1 == dep[edge[j].v])
{
break;
}
}
if(cur[i])
{
ps[top ++] = cur[i];
i = edge[cur[i]].v;
}
else
{
if(top == 0)
{
break;
}
dep[i] = -1;
i = edge[ps[-- top]].u;
}
}
}
return res;
}
int main()
{
int i,j,a,b,s,t,f,n,d;
char str[205];
while(~scanf("%d%d%d",&n,&f,&d))
{
s=0;
t=f+n+d+10+n;
ne=2;
memset(head,0,sizeof(head));
for(i=1;i<=f;i++)
{
scanf("%d",&a);
addedge(s,i,a);
}
for(i=1;i<=d;i++)
{
scanf("%d",&a);
addedge(f+n+n+i,t,a);
}
for(i=1;i<=n;i++)
{
addedge(f+i,f+n+i,1);
}
for(i=1;i<=n;i++)
{
scanf("%s",str);
for(j=1;j<=f;j++)
{
if(str[j-1]=='Y')
{
addedge(j,f+i,inf);
}
}
}
for(i=1;i<=n;i++)
{
scanf("%s",str);
for(j=1;j<=d;j++)
{
if(str[j-1]=='Y')
{
addedge(f+n+i,f+n+n+j,inf);
}
}
}
printf("%d\n",dinic(s,t));
}
return 0;
}