BUPT校内训练 & HDU 5294 最短路&最小割

文章来自  Icontofig 's Blog // 我们的征程是星辰大海!Away From OI,Come to ICPC(查看友链请点About Me)

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 number is N. And there are M channels connecting the chambers. Innocent Wu wants to catch up Dumb Zhang to find out the answers of some questions, however, it’s Dumb Zhang’s intention to keep Innocent Wu in the dark, to do which he has to stop Innocent Wu from getting him. Only via the original shortest ways from the entrance to the end of the tomb costs the minimum time, and that’s the only chance Innocent Wu can catch Dumb Zhang.
Unfortunately, Dumb Zhang masters the art of becoming invisible(奇门遁甲) and tricks devices of this tomb, he can cut off the connections between chambers by using them. Dumb Zhang wanders how many channels at least he has to cut to stop Innocent Wu. And Innocent Wu wants to know after how many channels at most Dumb Zhang cut off Innocent Wu still has the chance to catch Dumb Zhang.

Input

There are multiple test cases. Please process till EOF.
For each case,the first line must includes two integers, N(<=2000), M(<=60000). N is the total number of the chambers, M is the total number of the channels.
In the following M lines, every line must includes three numbers, and use ai、bi、li as channel i connecting chamber ai and bi(1<=ai,bi<=n), it costs li(0<li<=100) minute to pass channel i.
The entrance of the tomb is at the chamber one, the end of tomb is at the chamber N.

Output

Output two numbers to stand for the answers of Dumb Zhang and Innocent Wu’s questions.

Sample Input

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

Sample Output

2 6

题目大意

给出一个n个点,m条边的有权无向图,求出删去最少条边数可以使得图没有一开始的最短路径,以及最短路上的边最多删除多少使得1还能走到n(题目中说只有在最初的最短路的时间内才能到达终点)


题解

首先我们肯定要求出最短路的长度,然后去根据算出的dist数组来找出所有的最短路。
算出dist数组后,我们在寻找所有最短路径时,对于一个出发点i和它的相邻点j,如果dist[i] + e.dist = dist[j],那么这条边一定属于某一个最短路径。
将所有最短路径包含的边重新建图,然后跑一遍BFS求出1——n的新的最短路,用新图的边的总数减去这个最短路的长度就是第二问的答案了。
那么第一问怎么求?删去最少条边使得最初的图的最短路不再存在。
删除,这很明显符合最小割的性质,由最小割最大流定理,我们对于我们新建的图跑一边最大流就能求出这个最小割,即第一问答案。


代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2005;
const int maxm = 6e4+5;
int get_num(){
    int num = 0;
    char c;
    bool flag = false;
    while((c = getchar()) == ' ' || c == '\r' || c == '\n');
    if(c == '-')
        flag = true;
    else num = c - '0';
    while(isdigit(c = getchar()))
        num = (((num<<2)+num)<<1) + c - '0';
    return (flag ? -1 : 1) * num;
}
struct edge{
    int to,next,d;
}ed[maxm<<1];
int h[maxn];
struct flow_di{
    int fr,to,next,cap;
}e[maxm<<2];
const int INF = 1e9+7;
int g[maxn];
int dis[maxn],dis2[maxn],vis[maxn],cur[maxn];
int num,cnt;
int n,m;
int s,t;
void init(){
    memset(ed,0,sizeof(ed));
    memset(e,0,sizeof(e));
    memset(h,-1,sizeof(h));
    memset(g,-1,sizeof(g));
    num = cnt = 0;
    return;
}
void add1(int u,int v,int dis){
    ed[num].to = v;ed[num].next = h[u];ed[num].d = dis;
    h[u] = num++;
    return;
}
void add2(int u,int v,int c){
    e[cnt].fr = u;e[cnt].to = v;e[cnt].cap = c;
    e[cnt].next = g[u];g[u] = cnt++;
    e[cnt].fr = v;e[cnt].to = u;e[cnt].cap = 0;
    e[cnt].next = g[v];g[v] = cnt++;
    return;
}
int ans = 0;
void spfa(int s){
    queueq;
    for(int i = 1;i <= n;++i)
        dis[i] = INF,vis[i] = 0;
    vis[s] = 1;
    q.push(s);
    dis[s] = 0;
    while(!q.empty()){
        int x = q.front();
        q.pop();
        vis[x] = 0;
        for(int i = h[x];i != -1;i = ed[i].next){
            int v = ed[i].to;
            if(dis[v] > dis[x] + ed[i].d){
                dis[v] = dis[x] + ed[i].d;
                if(!vis[v]){
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    return;
}
void spfa2(int s){
    queueq;
    for(int i = 1;i <= n;++i)
        dis[i] = INF,vis[i] = 0;
    vis[s] = 1;
    q.push(s);
    dis[s] = 0;
    while(!q.empty()){
        int x = q.front();
        q.pop();
        vis[x] = 0;
        for(int i = g[x];i != -1;i = e[i].next){
            int v = e[i].to;
            if(dis[v] > dis[x] + 1){
                dis[v] = dis[x] + 1;
                if(!vis[v]){
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    return;
}
bool BFS(int s,int t){
    queueq;
    for(int i = s;i <= t;++i)
        dis2[i] = -1,vis[i] = 0;
    vis[s] = 1;
    dis2[s] = 0;
    q.push(s);
    while(!q.empty()){
        int x = q.front();
        q.pop();
        for(int i = g[x];i != -1;i = e[i].next){
            if(!vis[e[i].to] && e[i].cap > 0){
                dis2[e[i].to] = dis2[x] + 1;
                q.push(e[i].to);
                vis[e[i].to] = 1;
            }
        }
    }
    return (dis2[t] != -1);
}
int DFS(int x,int a){
    if(x == t || a == 0)return a;
    int flow = 0,f;
    for(int &i = cur[x];i != -1;i = e[i].next){
        if(dis2[x] + 1 == dis2[e[i].to]){
            f = min(e[i].cap,a - flow);
            f = DFS(e[i].to,f);
            flow += f;
            e[i].cap -= f;
            e[i^1].cap += f;
        }
    }
    return flow;
}
int dinic_flow(int s,int t){
    int flow = 0;
    while(BFS(s,t)){
        for(int i = 1;i <= n;++i)cur[i] = g[i];
        flow += DFS(s,INF);
    }
    return flow;
}
int u,v,l;
int main(){
    s = 1;
    while(scanf("%d%d",&n,&m) != EOF){
        init();
        for(int i = 1;i <= m;++i){
            u = get_num();
            v = get_num();
            l = get_num();
            add1(u,v,l);
            add1(v,u,l);
        }
        spfa(1);
        for(int i = 1;i <= n;++i)
            for(int j = h[i];j != -1;j = ed[j].next){
                if(dis[i] + ed[j].d == dis[ed[j].to])
                    add2(i,ed[j].to,1);
            }
        spfa2(1);
        t = n;
        int ans = dinic_flow(s,t),ans2 = m - dis[t];
        printf("%d %d\n",ans,ans2);
    }
    return 0;
}​
Sign in to leave a comment.
No Leanote account ? Sign up now.
0 comments
Title - Artist
0:00