8 9 1 2 2 2 3 2 2 4 1 3 5 3 4 5 4 5 8 1 1 6 2 6 7 5 7 8 1
2 6
无向图N个点M条边,输出最少删掉几条边破坏最短路。最多删掉几条边不破坏最短路。
最多删几条边不破坏最短路的答案是M减去最短路里边数最少的那个。最少删掉几条边破坏最短路的做法是把全部在最短路上的边又一次建图,变成流量为1的网络流,求最小割。
在求最短路的时候记录下上一节点。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int MAXN=2010;
int N,M;
struct Edge{
    int from,to,cap,flow;
};
struct Dinic{
    int n,m,s,t;            //结点数,边数(包含反向弧),源点编号和汇点编号
    vector<Edge> edges;     //边表。edge[e]和edge[e^1]互为反向弧
    vector<int> G[MAXN];    //邻接表,G[i][j]表示节点i和第j条边在e数组中的序号
    bool vis[MAXN];         //BFS使用
    int d[MAXN];            //从起点到i的距离
    int cur[MAXN];          //当前弧下标
    void clear_all(int n){
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }
    void clear_flow(){
        int len=edges.size();
        for(int i=0;i<len;i++) edges[i].flow=0;
    }
    void add_edge(int from,int to,int cap){
        edges.push_back((Edge){from,to,cap,0});
        edges.push_back((Edge){to,from,0,0});
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    bool BFS(){
        memset(vis,0,sizeof(vis));
        queue<int> q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            int len=G[x].size();
            for(int i=0;i<len;i++){
                Edge& e=edges[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow){
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int DFS(int x,int a){
        if(x==t||a==0) return a;
        int flow=0,f,len=G[x].size();
        for(int& i=cur[x];i<len;i++){
            Edge& e=edges[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
                e.flow+=f;
                edges[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }
    int maxflow(int s,int t){
        this->s=s;
        this->t=t;
        int flow=0;
        while(BFS()){
            memset(cur,0,sizeof(cur));
            flow+=DFS(s,INF);
        }
        return flow;
    }
    int mincut(){   //call this after maxflow
        int ans=0;
        int len=edges.size();
        for(int i=0;i<len;i++){
            Edge& e=edges[i];
            if(vis[e.from]&&!vis[e.to]&&e.cap>0) ans++;
        }
        return ans;
    }
    void reduce(){
        int len=edges.size();
        for(int i=0;i<len;i++) edges[i].cap-=edges[i].flow;
    }
}solver;
int d[MAXN];
vector<int> p[MAXN];
struct HeapNode{
    int u,d;
    bool operator < (const HeapNode& rhs) const{
        return d>rhs.d;
    }
};
struct Edge2{
    int u,v,dist;
};
struct Dijkstra{
    int n,m;
    vector<Edge2> edges;
    vector<int> G[MAXN];
    bool done[MAXN];
    void init(int n){
        this->n=n;
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }
    void add_edge(int u,int v,int dist){
        edges.push_back((Edge2){u,v,dist});
        m=edges.size();
        G[u].push_back(m-1);
    }
    void dijkstra(int s){
        priority_queue<HeapNode> q;
        for(int i=0;i<n;i++) p[i].clear();
        for(int i=0;i<n;i++) d[i]=INF;
        d[s]=0;
        memset(done,0,sizeof(done));
        q.push((HeapNode){s,0});
        while(!q.empty()){
            HeapNode x=q.top();
            q.pop();
            int u=x.u;
            if(done[u]) continue;
            done[u]=true;
            int L=G[u].size();
            for(int i=0;i<L;i++){
                Edge2& e=edges[G[u][i]];
                if(d[e.v]>d[u]+e.dist){
                    d[e.v]=d[u]+e.dist;
                    p[e.v].clear();
                    p[e.v].push_back(u);
                    q.push((HeapNode){e.v,d[e.v]});
                }
                else if(d[e.v]==d[u]+e.dist){
                    p[e.v].push_back(u);
                    q.push((HeapNode){e.v,d[e.v]});
                }
            }
        }
    }
}solver2;
int num[MAXN];
int dfs(int u){
    if(u==0) return 0;
    if(num[u]!=INF) return num[u];
    int len=p[u].size();
    for(int i=0;i<len;i++){
        int fa=p[u][i];
        solver.add_edge(fa,u,1);
        solver.add_edge(u,fa,1);
        num[u]=min(num[u],dfs(fa)+1);
    }
    return num[u];
}
int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&N,&M)!=EOF){
        solver2.init(N+1);
        int u,v,t;
        for(int i=0;i<M;i++){
            scanf("%d%d%d",&u,&v,&t);
            u--;
            v--;
            solver2.add_edge(u,v,t);
            solver2.add_edge(v,u,t);
        }
        solver2.dijkstra(0);
        memset(num,INF,sizeof(num));
        solver.clear_all(N+1);
        int n=dfs(N-1);
        solver.maxflow(0,N-1);
        int ans1=solver.mincut(),ans2=M-num[N-1];
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}
hdu5294 Tricks Device 最短路+最小割 多校联合第一场
原文:http://www.cnblogs.com/ljbguanli/p/6726045.html