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 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

Author

FZUACM

Source

2015 Multi-University Training Contest 1

题意:

吴天真和张起灵分别在一个墓地的入口和出口

吴天真准备到出口找张起灵

已知这个墓地有N个房间,入口编号为1,出口编号为N,这N个房间有M条隧道连接

给出吴天真经过每一个隧道需要的时间

设吴天真从入口到达出口的最短时间为T

则张只会在出口处逗留T的时间,超过这个时间张就会离开,天真就再也找不到他了

由于张不希望被天真找到,所以张会施展他的奇门遁甲:

张可以指定若干隧道,被指定的隧道将会消失。

现在问题来啦:

张问你:他最少需要指定多少条隧道,才可以保证天真找不到他

天真也要问你:在保证天真可以找得到张的情况下, 张最多可以指定多少条隧道消失。

分析:

由于天真从1到达N所走的路径必须是最短路径,所以若一条路径不是最短路径,就不用管它了。

从1到N的最短路径不止一条,那么天真的问题等价为:

天真走那条隧道数最少的最短路径,若有x条边,则第二问的答案为总隧道数-x

如果对这个图重新建立,只保留所有的最短路径的边,则张的问题等价为:

求出这个新图的最小割。

而我们知道,一个图的最小割就等于最大流,所以求最大流就可以了。

而他要求的是最小割的边的总数啊?

只要我们建立新图的时候,把边的容量初始化为1,那么最后求得的最大流=最小割=最小割的边数

不过,我又有一个想法,如果先用dinic求出最大流,在level[T]<0的时候,对这个图的每一个节点,若level[i]>=0

则i是在集合S,若level[i]<0,则i是在集合T

然后遍历每一条边,如果边的起点在S,终点在T,则边数++

遍历完成后,边数就是割的边数了。

不过这样wa了,这个想法可以?我再去想想。

所以算法流程为:

1.保证天真走的是最短路的条件下,从1到达N的最少隧道数。

2.只保留所有的最短路径的边,建立新图

3.求出这个图的最大流

这道题我遇见了几个很好的情况,也说说:

1.以前做的题只要求出最短路的长度就可以了,这个要求的是最短路中边数最少的那一条路径的边数

做法:

加一个cnt数组,cnt[i]表示节点i到起点的最短路的最少边数

cnt[起点]=0,cnt[其他]=INF

然后spfa的同时更新cnt的值就好了

2.找出1到N所有的最短路径的边,建立新图

做法:

在求出起点到所有点的最短路径dis后,

遍历每一条边e,若dis[e.to]==dis[e.from]+e.cost

则边e是起点1到达点e.to的其中一条最短路径的边,加入,容量这道题是1

因为这条边有可能就是起点1到终点N的其中一条最短路径的边

3.求最小割的边数

做法:

当所有边的容量都是1的时候,最小割的边数=最小割=最大流

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<queue>
  5 #include<vector>
  6
  7 using namespace std;
  8
  9 const int  MAXN=2010;
 10 const int INF=0x3f3f3f3f;
 11
 12 struct Edge1
 13 {
 14     int to,cost;
 15 };
 16 struct Edge2
 17 {
 18     int to,cap,rev;
 19 };
 20
 21 vector<Edge1>edge1[MAXN];
 22 vector<Edge2>edge2[MAXN];
 23
 24 void addedge1(int from,int to,int cost)
 25 {
 26     edge1[from].push_back((Edge1){to,cost});
 27     edge1[to].push_back((Edge1){from,cost});
 28 }
 29 void addedge2(int from,int to,int cap)
 30 {
 31     edge2[from].push_back((Edge2){to,cap,edge2[to].size()});
 32     edge2[to].push_back((Edge2){from,0,edge2[from].size()-1});
 33 }
 34
 35 int iter[MAXN];
 36 int level[MAXN];
 37 int in[MAXN];   //求割的时候
 38 int vis[MAXN];
 39 int dis[MAXN];
 40 int cnt[MAXN];
 41
 42 void init(int N)
 43 {
 44     for(int i=0;i<=N;i++)
 45     {
 46         edge1[i].clear();
 47         edge2[i].clear();
 48     }
 49 }
 50
 51 void spfa(int N)
 52 {
 53     for(int i=1;i<=N;i++)
 54     {
 55         dis[i]=INF;
 56         cnt[i]=INF;
 57     }
 58     memset(vis,false,sizeof(vis));
 59
 60     queue<int>que;
 61     while(!que.empty())
 62         que.pop();
 63
 64     int str=1;
 65     que.push(str);
 66     vis[str]=true;
 67     dis[str]=0;
 68     cnt[str]=0;
 69
 70     while(!que.empty())
 71     {
 72         int u=que.front();
 73         que.pop();
 74         vis[u]=false;   //重要
 75         for(int i=0;i<edge1[u].size();i++)
 76         {
 77             Edge1 &e=edge1[u][i];
 78             if(dis[e.to]==dis[u]+e.cost)
 79                 cnt[e.to]=min(cnt[e.to],cnt[u]+1);
 80             if(dis[e.to]>dis[u]+e.cost)
 81             {
 82                 dis[e.to]=dis[u]+e.cost;
 83                 cnt[e.to]=cnt[u]+1;
 84                 if(!vis[e.to])
 85                 {
 86                     vis[e.to]=true;
 87                     que.push(e.to);
 88                 }
 89             }
 90         }
 91     }
 92     return ;
 93 }
 94
 95 void build_group(int N)
 96 {
 97     for(int i=1;i<=N;i++)
 98     {
 99         for(int j=0;j<edge1[i].size();j++)
100         {
101             Edge1 &e=edge1[i][j];
102             if(dis[e.to]==dis[i]+e.cost)
103                 addedge2(i,e.to,1);
104         }
105     }
106 }
107
108 void bfs()
109 {
110     memset(level,-1,sizeof(level));
111     queue<int>que2;
112     while(!que2.empty())
113         que2.pop();
114     int s=1;
115     que2.push(s);
116     level[1]=0;
117     while(!que2.empty())
118     {
119         int u=que2.front();
120         que2.pop();
121         for(int i=0;i<edge2[u].size();i++)
122         {
123             Edge2 &e=edge2[u][i];
124             if(e.cap>0&&level[e.to]<0)
125             {
126                 level[e.to]=level[u]+1;
127                 que2.push(e.to);
128             }
129         }
130     }
131 }
132
133 int dfs(int u,int T,int f)
134 {
135     if(u==T)
136         return f;
137     for(int &i=iter[u];i<edge2[u].size();i++)
138     {
139         Edge2 &e=edge2[u][i];
140         if(e.cap>0&&level[e.to]>level[u])
141         {
142             int d=dfs(e.to,T,min(e.cap,f));
143             if(d>0)
144             {
145                 e.cap-=d;
146                 edge2[e.to][e.rev].cap+=d;
147                 return d;
148             }
149         }
150     }
151     return 0;
152 }
153
154 /*
155 int solve(int N)
156 {
157     for(int i=1;i<=N;i++)
158         in[i]=false;
159     for(int i=1;i<=N;i++)
160     {
161         if(level[i]>=0)
162             in[i]=true;
163     }
164
165     int res=0;
166
167     for(int i=1;i<=N;i++)
168     {
169         if(!in[i])
170             continue;
171         for(int j=0;j<edge2[i].size();j++)
172         {
173             Edge2 &e=edge2[i][j];
174             if(!in[e.to])
175                 res++;
176         }
177     }
178     return res;
179 }
180 */
181
182 int max_flow(int N)
183 {
184     int flow=0;
185     while(1)
186     {
187         bfs();
188         if(level[N]<0)
189             break;
190         memset(iter,0,sizeof(iter));
191         int f;
192         while(f=dfs(1,N,INF))
193         {
194             flow+=f;
195         }
196     }
197     //return solve(N);
198     return flow;
199 }
200
201 int main()
202 {
203     int N,M;
204     while(~scanf("%d%d",&N,&M))
205     {
206         init(N);
207
208         for(int i=1;i<=M;i++)
209         {
210             int from,to,cost;
211             scanf("%d%d%d",&from,&to,&cost);
212             addedge1(from,to,cost);
213         }
214
215         spfa(N);
216
217         build_group(N);
218
219         int cut=max_flow(N);
220
221         printf("%d %d\n",cut,M-cnt[N]);
222     }
223     return 0;
224 }

时间: 2024-10-07 05:16:20

HDU 5294 多校第一场1007题 最短路+最小割的相关文章

2014多校第一场A题 || HDU 4861 Couple doubi

题目链接 题意 : 有K个球,给你一个数P,可以求出K个值,(i=1,2,...,k) : 1^i+2^i+...+(p-1)^i (mod p).然后女朋友先取,再xp取,都希望赢,如果女朋友能赢输出YES,否则输出NO 思路 :这个题,在纸上算算差不多就出来结果了,因为要赢,所以一开始必定拿大的,根据规律可以发现最后的那个取余结果不是0就是某个数,所以就看那个数有奇数个还是偶数个即可. 官方题解: 1 #include <stdio.h> 2 #include <string.h&g

2014多校第一场 I 题 || HDU 4869 Turn the pokers(费马小定理+快速幂模)

题目链接 题意 : m张牌,可以翻n次,每次翻xi张牌,问最后能得到多少种形态. 思路 :0定义为反面,1定义为正面,(一开始都是反), 对于每次翻牌操作,我们定义两个边界lb,rb,代表每次中1最少时最少的个数,rb代表1最多时的个数.一张牌翻两次和两张牌翻一次 得到的奇偶性相同,所以结果中lb和最多的rb的奇偶性相同.如果找到了lb和rb,那么,介于这两个数之间且与这两个数奇偶性相同的数均可取到,然后在这个区间内求组合数相加(若lb=3,rb=7,则3,5,7这些情况都能取到,也就是说最后的

2014多校第一场D题 || HDU 4864 Task (贪心)

题目链接 题意 : 用N台机器,M个任务,每台机器都有一个最大工作时间和等级,每个任务有一个需要工作时间和一个等级.如果机器完成一个任务要求是:机器的工作时间要大于等于任务的时间,机器的等级要大于等于任务的等级.一台机器只能完成一个任务,一个任务只能被一台机器完成.每个机器完成一个任务公司能够获得500*xi+2*yi (此处xy都是指被完成的任务的).输出所有机器能完成的最多任务数,和最大盈利. 思路 :贪心,自己做的时候想了各种排序都不对,没有考虑到500*xi+2*yi 这个公式的重要性.

2014多校第一场J题 || HDU 4870 Rating(DP || 高斯消元)

题目链接 题意 :小女孩注册了两个比赛的帐号,初始分值都为0,每做一次比赛如果排名在前两百名,rating涨50,否则降100,告诉你她每次比赛在前两百名的概率p,如果她每次做题都用两个账号中分数低的那个去做,问她最终有一个账号达到1000分需要做的比赛的次数的期望值. 思路 :可以直接用公式推出来用DP做,也可以列出210个方程组用高斯消元去做. (1)DP1:离散化.因为50,100,1000都是50的倍数,所以就看作1,2,20.这样做起来比较方便. 定义dp[i]为从 i 分数到达i+1

2014多校第一场 E 题 || HDU 4865 Peter&#39;s Hobby (DP)

题目链接 题意 : 给你两个表格,第一个表格是三种天气下出现四种湿度的可能性.第二个表格是,昨天出现的三种天气下,今天出现三种天气的可能性.然后给你这几天的湿度,告诉你第一天出现三种天气的可能性,让你求出最可能出现的天气序列 . 思路 : 定义第 i 天叶子湿度为hum[i].第 i 天,天气为 j 的最大概率为dp[i][j].wealea[i][j]表示天气为 i 叶子为j的概率,weawea[i][j]表示今天天气为 i 明天天气为j的概率,st[i]表示第一天天气为i的概率.pre[i]

15年多校第一场七题hdu5294

要做这题,先要明白图的割,说白了就是 为了让原点无法到汇点要删几条边(之所以叫割,就是在图面上切一刀,减掉最小的边是原点和汇点成为两个集合),想到了割先放着一会用. 题中说只有沿最短路走才有可能追上,那么就意味着图中的最短路可能不止一条,沿着最短路走才能追上,那么其他的走法就没用了,所以只要求原点到汇点的最短路径图的最小割就可以知道最少断几条边可以堵住人了,再说第二问,既然最短路不止一条,那么只要边数量最小的一条最短路不被堵上,那个人就能追上炸弹张了,其他的边都可以赌上一点问题没有,这样就是总点

Card Hand Sorting 18中南多校第一场C题

一.题意 随机给你一堆牌(标准扑克牌),之后让你按照: 第一优先规则:所有相同花色的在一起 第二优先规则:所有相同花色的必须按照升序或者降序排列 问,你最少要拿出多少张牌插入到其他的地方以维持这个状况? 二.做法 考虑,4种花色,因而排列有A44(24种): 考虑升降续组合,为2^4=16种 因而所有合法最终状态共有24*16种状态,因而可以进行枚举. 对于变化次数有,n-LCS(i); 故,枚举取最大即可. 最大时间复杂度为:52*52+14*16*52*log52; (因为最大卡牌数量为52

Highest Tower 18中南多校第一场H题

一.题意 给出N个方块,要求给出一个方案,使得1. 所有方块都被使用到(题目数据保证这点) 2.所有方块垒成一个塔,且上面的方块宽度小于下面的方块 3.每个方块只能用一次,可以横着或者竖着. n范围50w 二.题解 首先考虑表示一个正方形的方法:长度和宽度组成的无向图. 因为必然要把所有方块都堆好,所以仅考虑冲突情况:即一个边长出现了多次(如果仅仅出现了一次就无须考虑,直接无缝的塞进适应的位置即可). 因而仅仅需要考虑连成片的图(联通块情况) 对于一个图,都会有如下设定: 1.每条边最多只能做一

杭电多校第一场补题-1002 Balanced Sequence

1002: Balanced Sequence 题意:给定n个字符串,n的大小在1e5左右,字符串的长度也是1e5,字符串仅由'('或')'组成,合法串可以不是连续的,将这n个串按照一定的顺序排列起来,使得组合之后的字符串的合法串的长度最长.n*len的大小是1e6 思路:首先n*len的处理出来每一个字符串中合法的长度,处理的办法可以参考之前栈的想法,每遇见一个')',就判断前面'('的个数,只要不为0,此时就可以合成一个合法串,处理完之后可以得到剩下的')'和'('的个数,然后所有的n个串进