HDU2485 Destroying the bus stations 最大流~Floyd+Dinic
2017-01-19 14:18
387 查看
Destroying the bus stations Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2809 Accepted Submission(s): 933 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
题意:
最少删除几个点,使得 1 到 n 的最短距离 >= k
显然 ,在图中 ,最短路 >= k 的点毫无意义 ,只有能够使得s->t的最短路 < k 的边才有意义
那跑一边Floyd ,如果dis[s][u]+dis[v][t] < k 表明(u,v)这条边可以使dis[s][t] < k (注意统计的是点数 不是边数 dis[s][u]+dis[v][t]不需要再+1)
保留这些边 ,其他全部删除 ,问题便转化为 最少删掉几个点 ,使s->t不联通
根据最大流最小割定理
当网络流中所有边权值为 1 ,使得s->t不联通 ,需要删除的边数就等于s->t的最大流
如果将图中每个点拆点 ,分为一个入点,一个出点,入点 到 出点 有一条权值为 1 的边 (s 和 t 拆点的权值为INF) 那删除 入点 到 出点 之间的边 ,就等价于删除掉这个点
所以 对Floyd处理后的图进行拆点 再跑一遍最大流
#include<iostream> #include<stdlib.h> #include<stdio.h> #include<string> #include<vector> #include<deque> #include<queue> #include<algorithm> #include<set> #include<map> #include<stack> #include<time.h> #include<math.h> #include<list> #include<cstring> #include<fstream> //#include<memory.h> using namespace std; #define ll long long #define ull unsigned long long #define pii pair<int,int> #define INF 1000000007 #define pll pair<ll,ll> #define pid pair<int,double> const int N = 2*50 + 5;//点数 const int M = 4000*3 + 5;//边数*2(包括反向边) int level ;//标号 level[i]:s到i的最短距离 struct Edge{ int to,c,next; }edge[M]; int head ; pii edge_pii[M]; inline void add_edge(int k,int u,int v,int c){ edge[k].to = v; edge[k].c = c; edge[k].next = head[u]; head[u] = k; } bool bfs(int s,int t,int n){//标号 计算level deque<int>que; fill(level,level+n+1,-1); que.push_back(s); level[s] = 0; while(!que.empty()){ int u = que.front(); if(u == t){ return true; } que.pop_front(); 147f3 for(int i = head[u];i!=-1;i = edge[i].next){ if(edge[i].c > 0 && level[edge[i].to] == -1){ level[edge[i].to] = level[u] + 1; que.push_back(edge[i].to); } } } return false; } int dfs(int u,int t,int maxf){//u:所在的点 t:汇点 maxf:能流到u的流量 if(u == t){ return maxf; } int sum = 0; for(int i = head[u];i!=-1;i = edge[i].next){ const Edge&e = edge[i]; if(e.c>0 && level[e.to]>level[u]){ int f = dfs(e.to,t,min(maxf - sum,e.c)); sum += f; edge[i].c -= f; edge[i^1].c += f; if(sum == maxf){//流量用完了 return sum; } } } return sum; } int dinic(int s,int t,int n){//s:源点 t:汇点 n:点数 int ans = 0; while(bfs(s,t,n)){ ans += dfs(s,t,INF); } return ans; } int dis ; void floyd(int n){ for(int k=1;k<=n;++k){ for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]); } } } } int main() { //freopen("/home/lu/Documents/r.txt","r",stdin); //freopen("/home/lu/Documents/w.txt","w",stdout); int n,m,k; while(scanf("%d%d%d",&n,&m,&k),n){ fill(head,head+2*n+1,-1); for(int i=1;i<=n;++i){ fill(dis[i],dis[i]+n+1,INF); dis[i][i]=0; } for(int i=0;i<m;++i){ int&u=edge_pii[i].first,&v=edge_pii[i].second; scanf("%d%d",&u,&v); dis[u][v]=1; } floyd(n); int num_e=0; for(int i=1;i<=n;++i){ if(i==1||i==n){ add_edge(num_e++,i,i+n,INF); add_edge(num_e++,n+i,i,0); continue; } add_edge(num_e++,i,i+n,1); add_edge(num_e++,i+n,i,0); } for(int i=0;i<m;++i){ int&u=edge_pii[i].first,&v=edge_pii[i].second; if(dis[1][u]+dis[v] <k){//此处巨坑 因为需要统计点数而非边数 所以dis[1][u]+dis[v] +1是错的 add_edge(num_e++,u+n,v,1); add_edge(num_e++,v,u+n,0); } } printf("%d\n", dinic(1,2*n,2*n)); } return 0; }
相关文章推荐
- HDU2485 Destroying the bus stations(floyd+最大流)
- hdu 2485 Destroying the bus stations【最大流Dinic+最短路floyd】好题
- hdu 2485 Destroying the bus stations【网络最大流】
- HDOJ 2485 Destroying the bus stations 最大流最小割
- HDU 2485 Destroying the bus stations(!最大流∩!费用流∩搜索)
- HDU 2485 Destroying the bus stations(最短路判定边+最大流)
- HDU2485(Destroying the bus stations)BFS+DFS
- HDU2485 Destroying the bus stations (POJ3921)
- POJ 3921 Destroying the bus stations 最大流
- HDU2485 Destroying the bus stations 迭代加深搜索
- HDU2485 Destroying the bus stations(最小割---点割)
- POJ3921 && HDU 2485 Destroying the bus stations(最大流 or 费用流)
- hdoj 2485 Destroying the bus stations 【最小割 + 最短路】
- HDUOJ----2485 Destroying the bus stations(2008北京现场赛A题)
- 【hdu】2485 Destroying the bus stations【最小割】
- POJ 3921 - Destroying the bus stations 构图最小费用最大流..
- hdu 2485 Destroying the bus stations
- HDU 2485 Destroying the bus stations
- POJ 3921 Destroying the bus stations
- POJ 3921 Destroying the bus stations 迭代加深搜索