题意:
给一个有向无环带权图,每条路径上最多只能割一条边,最后使1到n无路径,问最小割边边权和是多少。
题意很清楚,但是这道题的题解其实是只适用于很少的情况的
我们考虑的做法是网络流最小割
对于所有边的反向边,流量均为inf
那么如果具体分析原因其实是这条路径割上游,那条路径割下游,然而可以走这条路径的上游和那条路径的下游,如何避免?
考虑到那条路径的上游和这条路径的下游是没有割的,中间的边如果可以反着走那么就可以很好的避免这种情况的发生
所以如果反向边是inf就可以很好的解决这个问题了
但是这样子想未必太过美好了一点,例如:
如果在网络流的图中有一条边是反向建的,那么正向的流量就是inf,导致答案与正确答案不符
无论如何,这道题的思路还是很好的,下贴代码
#include<bits/stdc++.h>
using namespace std;
const int inf=0x7fffffff;
int tot=1,w[2005],remain[2005],to[2005],nxt[2005];
int head[305],depth[305],hh[305];
int n,m,shu1,shu2,shu3,ans;
queue <int> que;
int minn(int x,int y)
{
if(x<y) return x;
return y;
}
void add(int x,int y,int z)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
remain[tot]=z;
}
bool bfs()
{
que.push(1);
memset(depth,0,sizeof(depth));
depth[1]=1;
while(!que.empty())
{
int x=que.front();
que.pop();
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(!remain[i]||depth[y]) continue;
depth[y]=depth[x]+1;
que.push(y);
}
}
return depth[n];
}
int dfs(int x,int delta)
{
if(x==n) return delta;
int sum=0;
for(int &i=hh[x];i&δi=nxt[i])
{
int y=to[i];
if(depth[y]!=depth[x]+1||!remain[i]) continue;
int flow=minn(remain[i],dfs(y,delta));
remain[i]-=flow;
remain[i^1]+=flow;
sum+=flow;
delta-=flow;
}
return sum;
}
int main()
{
freopen("mer.in","r",stdin);
freopen("mer.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&shu1,&shu2,&shu3);
add(shu1,shu2,shu3);
add(shu2,shu1,inf/3);
}
while(bfs())
{
for(int i=1;i<=n;i++)
hh[i]=head[i];
ans+=dfs(1,inf);
}
cout<<ans;
return 0;
}