HDU6582 Path(最短路+最小割)

题意:

查询一个边集,使得这个图里起点到终点的最短路径变长。

题解:

先用spfa跑一遍最短路,把不在最短路径上的边权设为0,然后跑一遍Dinic算法求最大流/最小割。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const ll inf=1e18;
const int maxn=1e5;
int N,M,T;
int head[maxn];
int tol;
struct node {
    int u;
    int v;
    ll w;
    int next;
}edge[maxn];
void addedge (int u,int v,ll w) {
    edge[tol].u=u;
    edge[tol].v=v;
    edge[tol].w=w;
    edge[tol].next=head[u];
    head[u]=tol++;
}
ll d[maxn];
int visit[maxn];
void spfa (int s) {
    for (int i=1;i<=N;i++)
        d[i]=inf; 
    d[s]=0;
    queue<int> q;
    q.push(s);
    visit[s]=1;
    while (!q.empty()) {
        int u=q.front();
        q.pop();
        visit[u]=0;
        for (int i=head[u];i!=-1;i=edge[i].next) {
            int v=edge[i].v;
            if (edge[i].w>0&&d[v]>d[u]+edge[i].w) {
                d[v]=d[u]+edge[i].w;
                if (!visit[v]) {
                    q.push(v);
                    visit[v]=1;
                }
            }
        }
    } 
}

ll dep[maxn];
ll inque[maxn];
ll vi;
ll cur[maxn];
ll maxflow=0;
int s,t;
bool bfs () {
    for (int i=0;i<=N;i++) 
        cur[i]=head[i],dep[i]=inf,inque[i]=0;
    dep[s]=0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int u=q.front();
        q.pop();
        inque[u]=0;
        for (int i=head[u];i!=-1;i=edge[i].next) {
            int v=edge[i].v;
            if (dep[v]>dep[u]+1&&edge[i].w) {
                dep[v]=dep[u]+1;
                if (inque[v]==0) {
                    q.push(v);
                    inque[v]=1;
                }
            }
        }
    } 
    if (dep[t]!=inf) return 1;
    return 0;
}

ll dfs (int u,ll flow) {
    ll increase=0;
    if (u==t) {
        vi=1;
        maxflow+=flow;
        return flow;
    }
    ll used=0;
    for (int i=cur[u];i!=-1;i=edge[i].next) {
        cur[u]=i;
        int v=edge[i].v;
        if (edge[i].w&&dep[v]==dep[u]+1) {
            if (increase=dfs(v,min(flow-used,edge[i].w))) {
                used+=increase;
                edge[i].w-=increase;
                edge[i^1].w+=increase;
                if (used==flow) break;
            }
        }
    }
    return used;
}


ll Dinic () {
    while (bfs()) {
        vi=1;
        while (vi==1) {
            vi=0;
            dfs(s,inf);
        }
    }
    return maxflow;
}
int main () {
    scanf("%d",&T);
    while (T--) {
        memset(head,-1,sizeof(head));
        tol=0;
        maxflow=0;
        scanf("%d%d",&N,&M);
        for (int i=1;i<=M;i++) {
            int u,v;
            ll w;
            scanf("%d%d%lld",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,0);
        }
        spfa(1);
        for (int i=1;i<=N;i++) {
            for (int j=head[i];j!=-1;j=edge[j].next) 
                if (d[edge[j].v]!=d[i]+edge[j].w) 
                    edge[j].w=0;
        }
        s=1;
        t=N;
        printf("%lld\n",Dinic());
    }
    return 0;
}

 

posted @ 2020-03-14 20:39  zlc0405  阅读(115)  评论(0编辑  收藏  举报