HDU2485 Destroying the bus stations (网络流+拆点)

题意:

给出一个有向图,询问最多删掉几个点,使得起点到终点的最短路大于k,起点和终点不能删。

题解:

先用Floyd处理出两两之间的最短路,然后对于每条边,如果d[1][x]+d[x][y]+d[y][n]<=k,则说明这条边是关键边。

然后拆点,对拆点后的图建立由关键边组成的网络,跑最大流即可。

需要注意的一点是,可以被删除的点,拆点边的容量是1。起点和终点不能被删除,把容量置为无限大即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
const int inf=1e9;
int n,m,k;
struct node {
    int u,v,w,nxt;
}edge[maxn<<1];
int head[maxn],tot;
void addedge (int u,int v,int w) {
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].nxt=head[u];
    head[u]=tot++;
    
    edge[tot].u=v;
    edge[tot].v=u;
    edge[tot].w=0;
    edge[tot].nxt=head[v];
    head[v]=tot++;
} 
int dep[maxn],inq[maxn],cur[maxn],wjm,maxflow,s,t;
bool bfs () {
    for (int i=0;i<=t;i++) {
        cur[i]=head[i];
        dep[i]=inf;
        inq[i]=0;
    }
    dep[s]=0;
    queue<int> q;
    q.push(s);
    while (q.size()) {
        int u=q.front();
        q.pop();
        inq[u]=0;
        for (int i=head[u];i!=-1;i=edge[i].nxt) {
            int v=edge[i].v;
            if (dep[v]>dep[u]+1&&edge[i].w) {
                dep[v]=dep[u]+1;
                if (inq[v]==0) {
                    q.push(v);
                    inq[v]=1;
                }
            }
        }
    }
    if (dep[t]!=inf) return 1;
    return 0;
}
int dfs (int u,int flow) {
    int increase=0;
    if (u==t) {
        wjm=1;
        maxflow+=flow;
        return flow;
    } 
    int used=0;
    for (int i=cur[u];i!=-1;i=edge[i].nxt) {
        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;
}
int Dinic () {
    while (bfs()) {
        wjm=1;
        while (wjm==1) {
            wjm=0;
            dfs(s,inf);
        }
    }
    return maxflow;
}
pair<int,int> e[maxn];
int g[1010][1010];
int main () {
    while (scanf("%d%d%d",&n,&m,&k)&&n&&m&&k) {
        for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) g[i][j]=1e6;
        for (int i=1;i<=m;i++) scanf("%d%d",&e[i].first,&e[i].second),g[e[i].first][e[i].second]=1;
        for (int i=1;i<=n;i++) g[i][i]=0;
        for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
        s=1;t=n*2+1;
        for (int i=0;i<=t;i++) head[i]=-1;tot=0;wjm=0;maxflow=0;
        addedge(s,1,inf);
        for (int i=2;i<n;i++) addedge(i,i+n,1);
        addedge(1,1+n,inf);
        addedge(n,n*2,inf);
        for (int i=1;i<=m;i++) {
            int x=e[i].first;
            int y=e[i].second;
            if (g[1][x]+g[x][y]+g[y][n]<=k) {
                addedge(x+n,y,1);
            }
        } 
        addedge(n*2,t,inf);
        printf("%d\n",Dinic());
    }
}

 

posted @ 2020-11-25 14:15  zlc0405  阅读(70)  评论(0编辑  收藏  举报