最大流的模板题,今天写了一个dinic的模板想测试一下,结果T到天荒地老,一度怀疑人生,到最后发现竟然是数组开小了。。。双向边数组要开两倍啊。。。
我这个智障……
啊。。。又一次智障了。。。写的模板有问题还一直没发现,后来去做另一道题T了无数发终于找到了错误……
在bfs过程中,判断这个点是否为t,即是否有一条可行的路时,我原来将判断语句放在每次出队之后,但是这样其实相当于把t放入队列中,然后进行后续的一堆操作,其实是无用的,会浪费很多时间,应该在每次刚刚遇到这个点时进行一次判断,如果不是t放入队列,如果是就直接返回。
再一次t到怀疑人生,关键是之前的模板测试题还没有发现这个问题QAQ
改正之后的模板……
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int maxm=1000010;
const int maxn=1010;
const int inf=0x3f3f3f3f;
int head[maxn],dis[maxn];
int cnt,m,n;
struct Edge{
int to,next,f;
}edge[maxm];
int s,t;
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int f)
{
edge[cnt].to=v;
edge[cnt].f=f;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].to=u; //增加一个反向边
edge[cnt].f=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue<int> que;
dis[s]=0;
que.push(s);
while(!que.empty())
{
int u=que.front();que.pop();
// if(u==t) return true; //写在这里会超时
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;int f=edge[i].f;
if(dis[v]==-1&&f>0)
{
dis[v]=dis[u]+1;
if(v==t) return true; //写在这里才是正确的
que.push(v);
}
}
}
return false;
}
int dfs(int x,int maxf)
{
if(x==t||maxf==0) return maxf;
int flow=0;
for(int i=head[x];~i;i=edge[i].next)
{
int v=edge[i].to;int f=edge[i].f;
if(dis[v]==dis[x]+1&&f)
{
f=dfs(v,min(f,maxf-flow));
edge[i].f-=f;
edge[i^1].f+=f;
flow+=f;
if(flow==maxf) return flow;
}
}
return flow;
}
int Dinic()
{
int ans=0;
while(bfs())
{
ans+=dfs(s,inf);
}
return ans;
}
int main()
{
int T,cas=0;
cin>>T;
while(T--)
{
init();
scanf("%d%d",&n,&m);
s=1;t=n;
for(int i=0;i<m;i++)
{
int u,v,f;
scanf("%d%d%d",&u,&v,&f);
add(u,v,f);
}
printf("Case %d: %d\n",++cas,Dinic());
}
return 0;
}