zoukankan      html  css  js  c++  java
  • 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
    ",Dinic());
        }
    }
  • 相关阅读:
    hdu4726
    hdu2709
    hdu4706
    hdu4715
    快速幂取模
    快速幂
    asp.net中页面传值
    微信小程序支付
    sql 查询重复记录值取一条
    bower使用
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14035835.html
Copyright © 2011-2022 走看看