50
【题解】【网络流最大流模板题】
EK:
#include
#include
#include
#include
using namespace std;
long long road[210][210],pre[210];
int n,m;
long long d[200010],h,t;
long long flow[210],ans;
int bfs(int f,int l)
{
h=t=0;
memset(d,0,sizeof(d));
int i,j;
for (i=1;i<=m;i++)
pre[i]=-1;
d[++t]=f; pre[f]=0; flow[f]=0x7ffffff;
while (h!=t)
{
int u;
h=(h%20010)+1;
u=d[h];
if (u==l) break;
for (i=1;i<=m;i++)
if (i!=f&&road[u][i]>0&&pre[i]==-1)
{
pre[i]=u;
flow[i]=min(road[u][i],flow[u]);
t=(t%20010)+1;
d[t]=i;
}
}
if (pre[l]==-1)
return -1;
else return flow[l];
}
long long find(int start,int end)
{
long long sum,s;
sum=s=0;
while ((s=bfs(start,end))!=-1)
{
int k,last;
k=end;
while (k!=start)
{
last=pre[k];
road[last][k]-=s;
road[k][last]+=s;
k=last;
}
sum+=s;
}
return sum;
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if (a==b) continue;
road[a][b]+=c;
}
ans=find(1,m);
printf("%lld",ans);
return 0;
}
#include
#include
#include
using namespace std;
long long tot,a[420],p[210],next[420],remain[420];
int cur[210],dis[210];
int d[20010],h,t;
int n,m;
long long ans,sum;
void add(int x,int y,int z)
{
tot++; next[tot]=p[x]; a[tot]=y; p[x]=tot; remain[tot]=z;
tot++; next[tot]=p[y]; a[tot]=x; p[y]=tot; remain[tot]=0;
return;
}
bool bfs()
{
int i;
memset(dis,-1,sizeof(dis));
h=0; t=1; d[1]=1; dis[1]=0;
for (i=1;i<=m;++i)
cur[i]=p[i];
while (h!=t)
{
int u,v;
h=(h%20010)+1;
u=d[h];v=p[u];
while (v>=0)
{
if (remain[v]&&dis[a[v]]<0)
{
dis[a[v]]=dis[u]+1;
t=(t%20010)+1;
d[t]=a[v];
}
v=next[v];
}
}
if (dis[m]<0)
return 0;
else return 1;
}
long long dfs(int now,int t,long long low)
{
if (!low||now==t) return low;
int u=cur[now],s1=0,s;
while (u>=0)
{
cur[now]=u;
if (dis[a[u]]==dis[now]+1&&(s=dfs(a[u],t,min(low,remain[u]))))
{
s1+=s; low-=s;
remain[u]-=s; remain[u^1]+=s;
if (!low) break;
}
u=next[u];
}
return s1;
}
int main()
{
int i,j;
memset(next,-1,sizeof(next));
memset(p,-1,sizeof(p));
scanf("%d%d",&n,&m);
for (i=1;i<=n;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
while (bfs())
while (sum=dfs(1,m,0x7fffffff))
ans+=sum;
printf("%lld",ans);
return 0;
}
#include
#include
#include
using namespace std;
int a[420],next[420],p[210],remain[420],tot;
int cur[210],dis[210],last[210],num[210];
int d[20010],h,t;
int n,m;
long long ans;
bool b[210];
inline void add(int x,int y,int s)
{
tot++; next[tot]=p[x]; a[tot]=y; p[x]=tot; remain[tot]=s;
tot++; next[tot]=p[y]; a[tot]=x; p[y]=tot; remain[tot]=0;
return;
}
inline int addflow(int s,int t)
{
int s1=0x7fffffff,now=t;
while (now!=s)
{
s1=min(s1,remain[last[now]]);
now=a[last[now]^1];
}
now=t;
while (now!=s)
{
remain[last[now]^1]+=s1;
remain[last[now]]-=s1;
now=a[last[now]^1];
}
return s1;
}
inline void bfs(int l)
{
int i;
for (i=1;i<=m;++i)
dis[i]=m;
memset(b,false,sizeof(b));
h=0; t=1; d[t]=l; dis[l]=0; b[l]=true;
while (h!=t)
{
int u,v;
h=(h%20010)+1;
u=d[h];
v=p[u];
while (v>=0)
{
if (!b[a[v]]&&remain[v^1])
{
b[a[v]]=true;
dis[a[v]]=dis[u]+1;
t=(t%20010)+1; d[t]=a[v];
}
v=next[v];
}
}
return;
}
inline long long isap(int s,int t)
{
int sum=0,now=s,i;
bfs(t);
for (i=1;i<=m;++i) num[dis[i]]++;//当前这种路径长度出现了几次
for (i=1;i<=m;++i) cur[i]=p[i];//当前弧
while (dis[s]=0)
{
if (dis[a[u]]+1==dis[now]&&remain[u])//有满足条件的出边
{
h=true;
cur[now]=u;
last[a[u]]=u;
now=a[u];
break;
}
u=next[u];
}
if (h==false)//没有满足条件的出边,重新编号(将层数小的重新编号)
{
int minn=n-1,u;
u=p[now];
while (u>=0)
{
if (remain[u])
minn=min(minn,dis[a[u]]);
u=next[u];
}
--num[dis[now]];
if (!num[dis[now]]) break;//如果重新编号后当前层没边了,则图不连通,不存在增广路了
dis[now]=minn+1;//重新编号
num[minn+1]++;
cur[now]=p[now];
if (now!=s) now=a[last[now]^1];
}
}
return sum;
}
int main()
{
int i;
memset(p,-1,sizeof(p));
memset(next,-1,sizeof(next));
tot=-1;
scanf("%d%d",&n,&m);
for (i=1;i<=n;++i)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
ans=isap(1,m);
printf("%lld",ans);
return 0;
}