传送门
简单解释一下如何求割的边数(即车数);
思路一:先用ISAP在原图中求最小割(即代价),然后将原图中的边权改为1,再求最小割(车数);
思路二:因为m<=1000,所以将原图边权改为edge*mod+1(mod为大于1000的任何数),代价即为当前图下的最小割/mod,车数即为当前图下最小割%mod
(记得开long long)
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
#define eps 1e-8
//#define mod 1e9+7
using namespace std;
const int mod=2001;
const int M=2e3+5;
const int N=4*1e6+5;//?????????? 4e8
int n,m,s,t;
struct node
{
int ver,edge,next;
}e[N];
int gap[N],d[N];
int tot=1,head[N];
void add(int x,int y,int z)
{
e[++tot].ver=y;
e[tot].edge=z;
e[tot].next=head[x];
head[x]=tot;
}
void addedge(int x,int y,int z)
{
add(x,y,z);add(y,x,0);
}
void bfs()
{
queue < int > q;
q.push(t);
d[t]=gap[1]=1;
while(q.size())
{
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
if(d[y]) continue;
d[y]=d[x]+1;
q.push(y);
gap[d[y]]++;
}
}
}
int dfs(int x,int flow)
{
if(x==t) return flow;
int rest=0,k;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
int z=e[i].edge;
if(!z) continue;
if(d[x]!=d[y]+1) continue;
k=dfs(y,min(z,flow-rest));
if(k<=0) continue;
rest+=k;
e[i].edge-=k;
e[i^1].edge+=k;
if(rest==flow) return rest;
}
if(--gap[d[x]]==0) d[s]=n+1;
++gap[++d[x]];
return rest;
}
int isap()
{
int maxflow=0;
bfs();
while(d[s]<=n) maxflow+=dfs(s,1<<30);
return maxflow;
}
void solve()
{
cin>>n>>m;
s=1,t=n;
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
addedge(x,y,z*mod+1);
}
int ans=isap();
cout<<ans/mod<<" "<<ans%mod<<endl;
}
signed main()
{
// ios::sync_with_stdio(false);
solve();
return 0;
}