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

题目大题:

求最多拆几条边图的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;
}

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

时间: 2024-10-10 23:48:49

【HDU 5294】Tricks Device(最短路+最大流)的相关文章

hdu 5294 Tricks Device 最短路建图+最小割

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 375    Accepted Submission(s): 98 Problem Description Innocent Wu follows Dumb Zh

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

题目链接:HDU 5294 Tricks Device 题意:n个点,m条边,并且一个人从1走到n只会走1到n的最短路径,问至少破坏几条边使原图的最短路不存在,最多破坏几条边使原图的最短路劲仍存在 思路: 1.跑一遍最短路,记录下所有最短路径,将这些最短路径的边以(0,1)(流量,容量)加到网络流中,跑一遍最大流 2.记录下的所有最短路径,再加到新的最短路的图中,边权为1,跑一遍最短路,m-最短路 就是答案 注意:有重边的情况 比如: 2 3 1 2 1 1 2 1 1 2 1 ans: 3 2

hdu 5294 Tricks Device(最短路 + 最大流)

hdu 5294 Tricks Device 题目大意:吴邪在古墓中追张起灵,古墓中有很多条路,走每条路都需要一个时间,吴邪只有在最短的时间从古墓的入口到达出口才能追上张起灵.但是张起灵很厉害,他可以使用奇门遁甲使一条路无法通行.现在,问,张起灵最少堵住几条路就可以使吴邪追不上他,以及在吴邪可以追上张起灵的情况下,张起灵最多能堵多少条路. 解题思路:先求出古墓中的最短路(耗时最少的路),再求最短路的同时,记录走最短路要通过哪几条路和走最短路最少通过的路数.最多能堵住的路就是总的路数减去走最短路所

HDOJ 5294 Tricks Device 最短路(记录路径)+最小割

最短路记录路径,同时求出最短的路径上最少要有多少条边, 然后用在最短路上的边重新构图后求最小割. Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1584    Accepted Submission(s): 388 Problem Description Innocent Wu follows Dumb Z

HDU 5294 Tricks Device(多校2015 最大流+最短路啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the entrance of the tomb while Dumb Zhang's at the end of it. The tomb is made up of many chambers, the total

hdu 5294 Tricks Device(2015多校第一场第7题)最大流+最短路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 题意:给你n个墓室,m条路径,一个人在1号墓室(起点),另一个人在n号墓室(终点),起点的那个人只有通过最短路径才能追上终点的那个人,而终点的那个人能切断任意路径. 第一问--终点那人要使起点那人不能追上的情况下可以切的最少的路径数,输出最少的路径数 第二问--起点那人能追上终点那人的情况下,终点那人能切断的最多的路径数,输出最多的路径数 思路:要使起点那人无法追上,只要使他的最短路径不存在就

hdu 5294 Tricks Device

求边最少最短路 求最短路构成的边权为1的图的最大流 两个 模板 #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <set> #include <map> #include <queue> #include <vector> #include <string> #include

HDU 5294(Tricks Device-最短路最小割)[Template:SPFA]

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2389    Accepted Submission(s): 635 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the en

hdu5294 Tricks Device 最短路+最小割 多校联合第一场

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 66    Accepted Submission(s): 14 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the entra

HDU 5294 多校第一场1007题 最短路+最小割

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1285    Accepted Submission(s): 302 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu’s at the ent