码迷,mamicode.com
首页 > 其他好文 > 详细

【HDU 5294】Tricks Device(最短路+最大流)

时间:2015-07-27 20:58:46      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

题目大题:

求最多拆几条边图的1 -> n的最小距离不会变

求最少拆几条边图的1 -> n的最小距离会变


最短路 + 网络流的问题


求出最短路径图(包含所有最短路径的图) 之后用m - (拥有最少边数的最短路径) 得到一个解

之后将最短路径图中的边重新建图(流量为1)求最大流



感觉写的比较麻烦,时间也正好卡着过的。

#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2005;
const int  INF = 2000000000;
struct W{
    int u,v,dist;
    W(int u,int v,int dist):u(u),v(v),dist(dist){};
};
struct Edge{
    int to,dist;
    Edge(int to = 0,int dist = 0):to(to),dist(dist){};
};
struct State{
    int pos,dist,num;
    State(int pos,int dist = 0,int num = 0):pos(pos),dist(dist),num(num){};
    friend bool operator < (State p,State q){
        if(p.dist != q.dist)
            return p.dist > q.dist;
        else
            return p.num > q.num;
    }
};
vector<W>edge;
//------------------------BFS最短路------------------------------------------
vector<Edge>G[maxn];
int n,m,vis[maxn];
int dist[maxn];
int min_dist,min_num;
int ans1,ans2;
void bfs(){
    min_dist = -1;
    min_num  = -1;
    priority_queue<State>q;
    memset(dist,-1,sizeof(dist));
    q.push(State(1,0,0));
    while(!q.empty()){
        State now = q.top(); q.pop();
        if(vis[now.pos]) continue;
        dist[now.pos] = now.dist;
        if(now.pos == n){
            min_dist = now.dist;
            min_num  = now.num;
        }
        vis[now.pos] = 1;
        for(int i = 0; i < G[now.pos].size(); i++){
            int to = G[now.pos][i].to;
            int dist = G[now.pos][i].dist;
            q.push(State(to,now.dist + dist,now.num + 1));
        }
    }
}
//----------------------------最大流--------------------------------------
struct W_Edge{
    int from,to,flow,cap;
    W_Edge(int from,int to,int flow,int cap):from(from),to(to),flow(flow),cap(cap){};
};
struct EdmondsKarp{;
    vector<W_Edge>w_edges;
    vector<int>w_G[maxn];
    int n,m;
    int a[maxn];        //起点到i的可改进量
    int p[maxn];
    void init(){
        w_edges.clear();
        for(int i = 0; i < maxn; i++) w_G[i].clear();
    }
    void add(int u,int v,int cap){
        w_edges.push_back(W_Edge(u,v,0,cap));
        w_edges.push_back(W_Edge(v,u,0,0));
        int m = w_edges.size();
        w_G[u].push_back(m - 2);
        w_G[v].push_back(m - 1);
    }
    int Maxflow(int s,int t){
        int flow = 0;
        for(;;){
            memset(a,0,sizeof(a));
            queue<int>Q;
            Q.push(s);
            a[s] = INF;
            while(!Q.empty()){
                int x = Q.front(); Q.pop();
                //printf("%d\n",x);
                for(int i = 0; i < w_G[x].size(); i++){
                    W_Edge & e = w_edges[w_G[x][i]];
                    if(!a[e.to] && e.cap > e.flow){
                        p[e.to] = w_G[x][i];
                        a[e.to] = min(a[x],e.cap - e.flow);
                        Q.push(e.to);
                    }
                }
                if(a[t]) break;
            }
            if(!a[t]) break;
            for(int u = t; u != s; u = w_edges[p[u]].from){
                w_edges[p[u]].flow += a[t];
                w_edges[p[u] ^ 1].flow -= a[t];
            }
            flow += a[t];
        }
        return flow;
    }
};
EdmondsKarp edm;
//----------------------------找在最短路径里的边--------------------------
void Find(){
    edm.init();
    int Size = edge.size();
    for(int i = 0; i < Size; i++){
        int d = dist[edge[i].u] - dist[edge[i].v];
        if(d == edge[i].dist){
            edm.add(edge[i].v,edge[i].u,1);
            //printf("%d -> %d\n",edge[i].v,edge[i].u);
        }
        else if(- d == edge[i].dist){
            edm.add(edge[i].u,edge[i].v,1);
            //printf("%d -> %d\n",edge[i].u,edge[i].v);
        }
    }
}
//----------------------------main----------------------------------------
int main(){
    while(scanf("%d%d",&n,&m) != EOF){
        for(int i = 1; i <= n; i++) G[i].clear();
        memset(vis,0,sizeof(vis));
        edge.clear();
        for(int i = 0; i < m; i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            G[x].push_back(Edge(y,z));
            G[y].push_back(Edge(x,z));
            edge.push_back(W(x,y,z));
        }
        bfs();
        Find();
        printf("%d %d\n",edm.Maxflow(1,n),m - min_num);
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

【HDU 5294】Tricks Device(最短路+最大流)

标签:

原文地址:http://blog.csdn.net/u013451221/article/details/47090311

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!