题面
题意
给出一幅有向无环图,问从点1到点n有几条互相没有交点(除起点终点外不能有公共点)的路径,保证路径数量最多的情况下,路径最大数量与最短的路径长度之和是多少.
分析
与费用流裸题不同的是,不能有公共点,解决方法是将每一个点拆为一个入点和一个出点,流量为1(起点终点不用拆或者流量为INF),建边时,从一个点的出点连向另外一点的入点,再跑一遍费用流即可.
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define N 510
#define M 200100
using namespace std;
int n,m,first[N],d[N],bb=1,ans,last[N],B[N],lc;
struct Bn
{
int to,next,quan,len;
}bn[M];
queue<int>que;
inline void add(int u,int v,int w,int z)
{
bb++;
bn[bb].to=v;
bn[bb].next=first[u];
bn[bb].quan=w;
bn[bb].len=z;
first[u]=bb;
}
inline void bfs()
{
int p,q,mn=INF;
bool in[N];
for(;!que.empty();que.pop());
memset(d,INF,sizeof(d));
memset(in,0,sizeof(in));
que.push(1);
d[1]=0;
for(;!que.empty();)
{
q=que.front();
que.pop();
in[q]=0;
for(p=first[q];p!=-1;p=bn[p].next)
{
if(d[bn[p].to]<=d[q]+bn[p].len||!bn[p].quan) continue;
d[bn[p].to]=d[q]+bn[p].len;
last[bn[p].to]=q;
B[bn[p].to]=p;
if(!in[bn[p].to])
{
in[bn[p].to]=1;
que.push(bn[p].to);
}
}
}
if(d[n]==INF) return;
lc+=d[n];
ans++;
for(p=n;p!=1;p=last[p])
{
bn[B[p]].quan--;
bn[B[p]^1].quan++;
}
bfs();
}
int main()
{
memset(first,-1,sizeof(first));
int i,j,p,q,o;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&p,&q,&o);
add(p+n,q,1,o);
add(q,p+n,0,-o);
}
for(i=2;i<n;i++) add(i,i+n,1,0),add(i+n,i,0,0);
add(1,n+1,INF,0),add(n+1,1,0,0),add(n,n*2,INF,0),add(n*2,n,0,0);
bfs();
cout<<ans<<" "<<lc;
}