Destroying the bus stations (hdu 2485 网络流+最短路)

Destroying the bus stations

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2313    Accepted Submission(s): 739

Problem Description

Gabiluso is one of the greatest spies in his country. Now he’s trying to complete an “impossible” mission ----- to make it slow for the army of City Colugu to reach the airport. City Colugu has n bus stations and m roads. Each road connects two bus stations
directly, and all roads are one way streets. In order to keep the air clean, the government bans all military vehicles. So the army must take buses to go to the airport. There may be more than one road between two bus stations. If a bus station is destroyed,
all roads connecting that station will become no use. What’s Gabiluso needs to do is destroying some bus stations to make the army can’t get to the airport in k minutes. It takes exactly one minute for a bus to pass any road. All bus stations are numbered
from 1 to n. The No.1 bus station is in the barrack and the No. n station is in the airport. The army always set out from the No. 1 station.

No.1 station and No. n station can’t be destroyed because of the heavy guard. Of course there is no road from No.1 station to No. n station.

Please help Gabiluso to calculate the minimum number of bus stations he must destroy to complete his mission.

Input

There are several test cases. Input ends with three zeros.

For each test case:

The first line contains 3 integers, n, m and k. (0< n <=50, 0< m<=4000, 0 < k < 1000)

Then m lines follows. Each line contains 2 integers, s and f, indicating that there is a road from station No. s to station No. f.

Output

For each test case, output the minimum number of stations Gabiluso must destroy.

Sample Input

5 7 3
1 3
3 4
4 5
1 2
2 5
1 4
4 5
0 0 0

Sample Output

2

Source

2008 Asia Regional Beijing

Recommend

gaojie   |   We have carefully selected several similar problems for you:  2491 2489 2492 2490 2487

题意:n个点m条边的图,求至少摧毁多少点可以使得从1到n的路径大于k。

思路:先预处理求出最短路,还要拆点,i与i‘之间连一条权为1的边,若边(u,v)满足dist1[u]+dist1[v]<k则添加 u‘ 到 v 的边,权为INF,求一次最大流即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define MAXN 1005
#define MAXM 10005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

struct Edge
{
    int to,next,cap,flow;
}edge[MAXM];

int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}

//加边,单向图三个参数,双向图四个参数
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u];
    edge[tol].flow=0; head[u]=tol++;
    edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v];
    edge[tol].flow=0; head[v]=tol++;
}

//输入参数:起点,终点,点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=start;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while (dep[start]<N)
    {
        if (u==end)
        {
            int Min=INF;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                if (Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for (int i=cur[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].to;
            if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if (flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for (int i=head[u];i!=-1;i=edge[i].next)
            if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        gap[dep[u]]--;
        if (!gap[dep[u]]) return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if (u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}

struct EDGE
{
    int u,v,w,next;
}E1[MAXM],E2[MAXM];

int n,m,k,num1,num2;
int head1[MAXN],head2[MAXN],dist1[MAXN],dist2[MAXN],inq[MAXN];

void init2()
{
    num1=0;num2=0;
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
}

void add1(int u,int v)
{
    E1[num1].u=u; E1[num1].v=v; E1[num1].w=1; E1[num1].next=head1[u]++; head1[u]=num1++;
}

void add2(int u,int v)
{
    E2[num2].u=u; E2[num2].v=v; E2[num2].w=1; E2[num2].next=head2[u]++; head2[u]=num2++;
}

void spfa(int s,int* head,int* dist,EDGE * E)
{
    queue<int>Q;
    memset(inq,0,sizeof(inq));
    dist[s]=0;
    inq[s]=1;
    Q.push(s);
    while (!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        for (int i=head[u];i+1;i=E[i].next)
        {
            int v=E[i].v;
            if (dist[v]>dist[u]+E[i].w)
            {
                dist[v]=dist[u]+E[i].w;
                if (!inq[v])
                {
                    inq[v]=1;
                    Q.push(v);
                }
            }
        }
    }
}

int main()
{
    int i,j,u,v;
    while (scanf("%d%d%d",&n,&m,&k))
    {
        if (n==0&&m==0&&k==0) break;
        init();
        init2();
        for (i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            add1(u,v);
            add2(v,u);
        }
        memset(dist1,INF,sizeof(dist1));
        memset(dist2,INF,sizeof(dist2));
        spfa(1,head1,dist1,E1);
        spfa(n,head2,dist2,E2);
        for (i=0;i<num1;i++)
        {
            if (dist1[E1[i].u]+dist2[E1[i].v]<k)
                addedge(E1[i].u+n,E1[i].v,INF);
        }
        for (i=1;i<=n;i++) addedge(i,i+n,1);
        printf("%d\n",sap(n+1,n,2*n));
    }
    return 0;
}
时间: 2024-10-07 12:33:51

Destroying the bus stations (hdu 2485 网络流+最短路)的相关文章

hdu 2485 Destroying the bus stations 迭代加深搜索

求最少去掉几个公交站使得从s到t的最短路径大于k. 迭代加深搜索. #include <cstdio> #include <cstring> #include <queue> using namespace std; #define maxn 60 #define maxm 50000 int n,m,K,cnt,up; int head[maxn],pre[maxn]; int road[maxn][maxn]; bool del[maxn]; queue<in

Destroying the bus stations

hdu2485:http://acm.hdu.edu.cn/showproblem.php?pid=2485 题意:给你一个图,让你删除其中的一些点,然后使得1到n的最小距离大于k,求删除的最小的点数. 题解:DFS枚举最短路径上的点. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #def

HDUOJ----2485 Destroying the bus stations

Destroying the bus stations Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2072    Accepted Submission(s): 647 Problem Description Gabiluso is one of the greatest spies in his country. Now he'

HDU2485 Destroying the bus stations(最小割---点割)

Destroying the bus stations Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2319    Accepted Submission(s): 743 Problem Description Gabiluso is one of the greatest spies in his country. Now he'

HDU 2485 Destroying the bus stations(费用流)

http://acm.hdu.edu.cn/showproblem.php?pid=2485 题意: 现在要从起点1到终点n,途中有多个车站,每经过一个车站为1时间,现在要在k时间内到达终点,问至少要破坏多少个车站. 思路: 把每个点拆分为两个点,容量为1,费用为0.之后相邻的车站连边,容量为INF,费用为1,表示经过一个车站需要1时间. 这样一来,跑一遍费用流计算出在费用不大于k的情况下的最大流,也就是最小割,即至少要破坏的车站数. 在网络中寻求关于f的最小费用增广路,就等价于在伴随网络中寻求

hdu 2485 Destroying the bus stations 最小费用最大流

题意: 最少需要几个点才能使得有向图中1->n的距离大于k. 分析: 删除某一点的以后,与它相连的所有边都不存在了,相当于点的容量为1.但是在网络流中我们只能直接限制边的容量.所以需要拆点来完成对的点容量的限制.对于边i -> j,先建边i ->i',再建i'->j.i ->i'只能建一次,容量为1,费用为0.i'->j的容量是INF.此题中因为已经有源点,所以源点(1)不能限制容量. 1 #include<iostream> 2 #include<c

HDU 2485 Destroying the bus stations

2015 ACM / ICPC 北京站 热身赛 C题 #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<algorithm> using namespace std; const int INF=0x7FFFFFFF; const int maxn=50+10;//点的数量 int n,m,k; in

HDU 3488Tour(网络流之最小费用流)

题目地址:hdu3488 这题跟上题基本差不多啊....详情请戳这里. 另外我觉得有要改变下代码风格了..终于知道了为什么大牛们的代码的变量名都命名的那么长..我决定还是把源点与汇点改成source和sink吧..用s和t太容易冲突了...于是如此简单的一道题调试到了现在..sad... 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #

hdu 2485 Highways

题意:Flatopia岛要修路,这个岛上有n个城市,要求修完路后,各城市之间可以相互到达,且修的总路程最短.求所修路中的最长的路段 最小生成树的一道题,很裸的一道题,不知道为什么就是编译过不了. #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int w[200000],u[200000],v[200000],p[5