Path

参考:[2019杭电多校第一场][hdu6582]Path(最短路&&最小割)

思路:这道题需要用到最短路和最小割。首先需要用最短路,找到最短的路径,然后再利用dis[e[j].s]+e[j].w==dis[e[j].t这个条件,重新建图,在重新建的图当中,保证了所有的路径长度都是最短路,那么便可以进行最小割的操作,最小割即最大流,所以,可以对新建的图写dinic求最大流

代码:

// Created by CAD on 2019/9/14.
#include <bits/stdc++.h>

#define INF 0x3f3f3f3f3f
#define mst(name, value) memset(name,value,sizeof(name))
#define ll long long
using namespace std;
const int maxn=3e5+10;
struct node {
    ll s, t, w, next;
} e[maxn << 1], e2[maxn << 1];
ll head[maxn], head2[maxn], cnt, cnt2;
void init()
{
    mst(head, -1), mst(head2, -1), cnt=cnt2=0;
}
void add(ll s, ll t, ll w)
{
    e[cnt].s=s, e[cnt].t=t, e[cnt].w=w, e[cnt].next=head[s];
    head[s]=cnt++;
}
void add2(ll s, ll t, ll w)
{
    e2[cnt2].s=s, e2[cnt2].t=t, e2[cnt2].w=w, e2[cnt2].next=head2[s];
    head2[s]=cnt2++;
}
struct p {
    ll dis, num;
    bool operator<(const p &a) const
    {
        return a.dis<dis;
    }
};
ll dis[maxn], vis[maxn],d[maxn];;
void dij(ll n)
{
    priority_queue<p> q;
    for (ll i=1; i<=n; ++i)
        dis[i]=INF, vis[i]=0;
    q.push({0, 1});
    dis[1]=0;
    while (!q.empty())
    {
        ll x=q.top().num;
        q.pop();
        if (vis[x])
            continue;
        vis[x]=1;
        for (ll i=head[x]; ~i; i=e[i].next)
        {
            ll y=e[i].t;
            if (dis[y]>dis[x]+e[i].w)
            {
                dis[y]=dis[x]+e[i].w;
                q.push({dis[y], y});
            }
        }
    }
}
bool bfs(ll s, ll t)
{
    queue<ll> q;
    mst(d, 0);
    d[s]=1;
    q.push(s);
    while (!q.empty())
    {
        ll x=q.front();
        q.pop();
        for (ll i=head2[x]; ~i; i=e2[i].next)
        {
            ll y=e2[i].t;
            if (e2[i].w && !d[y])
                d[y]=d[x]+1, q.push(y);
        }
    }
    return d[t];
}
ll dfs(ll x, ll t, ll lim)
{
    if (x==t) return lim;
    ll add, ans=0;
    for (ll i=head2[x]; ~i; i=e2[i].next)
    {
        ll y=e2[i].t;
        if (d[y]==d[x]+1 && e2[i].w)
        {
            add=dfs(y, t, min(lim, e2[i].w));
            e2[i].w-=add;
            e2[i^1].w+=add;
            ans+=add;
            lim-=add;
            if (!lim) break;
        }
    }
    if (!ans) d[x]=-1;
    return ans;
}
ll dinic(ll s, ll t)
{
    ll ans=0;
    while (bfs(s, t))
        ans+=dfs(s, t, INF);
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        ll n, m;
        init();
        cin >> n >> m;
        ll x, y, z;
        for (ll i=1; i<=m; ++i)
            cin >> x >> y >> z, add(x, y, z);
        dij(n);
        for (ll i=1; i<=n; ++i)
            for (ll j=head[i]; ~j; j=e[j].next)
                if (dis[e[j].s]+e[j].w==dis[e[j].t])
                    add2(e[j].s, e[j].t, e[j].w), add2(e[j].t, e[j].s, 0);
        cout << dinic(1, n) << endl;
    }
    return 0;
}