解题报告 之 HDU5294 Tricks Device

解题报告 之 HDU5294 Tricks Device

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个节点无向图,起点为1,终点为n。对于所有1到n的最短路集合所构成的子图中,第一问是至少要删几条边才能使得残余图1无法到n,第二问是在这个子图中最多删除几条边都还可以使得1可以到达n。

分析:首先必然面临一个问题,就是如何判断一条边是不是最短路上的边。一开始的想法是跑一次最短路,然后枚举每条边(u,v),如果1到u的最短路+uv长度=1到v的最短路,那么就说明是(u,v)是最短路。很遗憾这种思路是错误的,这只能证明这是u到v的最短路,但并不一定是1到n的最短路(看图你就明白了)。

比如上面这个图,如果按照之前的那种方法来弄,那么上面的四条边都会被加进去,下面两条边也会被加进去。但是其实是错的,因为上面的那条路根本不是最短路。所以我们需要改变方法,能够保证一条路是1 -> n的最短路的一段的方法是分别以1和N为源跑一次最短路,对于一条边(u,v),如果(1->u)min +
uv +(v->N)min == (1->N)min 则是最短路(当然也等于(N->1)min )。

好了,第一个问题解决了。我们先跑两个最短路,然后把是最短路上的边筛选出来,构建成新的子图。然后求第一问,要删除几条边,那么一看就是最小割了,最小割也是最大流。那么将子图的每一条边流量设置为1,再跑一下最大流则是答案。

那么第二问怎么弄呢?思路是,求出边数最少的一条最短路,再用总边数m-这条路边数就是答案。那么我们可以在子图上跑最短路,因为之前子图的流量(也可看成权值)已经被设为1了。那么此时在以1为源头在子图上跑一下最短路就是从1->N的所有最短路中边数最少的。(这里注意了,所谓最短路中边数最少的,是我们之前已经用所有是最短路的边来构造这个子图,已经保证了权重最小,然后再看边数最少)

上代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<deque>
#include<vector>
#include<utility>
using namespace std;

const int MAXN = 2510;
const int MAXM = 300010;
const int INF = 0x3f3f3f3f;

struct Edge
{
	int from, to, cap, next;
};

Edge edge[MAXM];
Edge edge2[MAXM];
int head[MAXN];
int head2[MAXN];
int level[MAXN];
int dis1[MAXN], dis2[MAXN];
int src, des, cnt, cnt2;

void SPFA(int *dis, int src,int n)
{
	int inqueue[MAXN] = {0};
	deque<int> q;
	dis[src] = 0;
	inqueue[src] = 1;
	q.push_front( src );

	while(!q.empty())
	{
		int u = q.front();
		q.pop_front();
		for(int i = head2[u]; i !=-1;i=edge2[i].next )
		{
			int v = edge2[i].to;
			if(dis[v]>dis[u]+edge2[i].cap)
			{
				dis[v] = dis[u] + edge2[i].cap;

				if(!inqueue[v])
				{
					if(!q.empty() && dis[v] > dis[q.front()])
						q.push_front( v );
					else
						q.push_back( v );
				}
			}
		}
	}
}

void addedge( int from, int to, int cap )
{
	edge[cnt].from = from;
	edge[cnt].to = to;
	edge[cnt].cap = cap;
	edge[cnt].next = head[from];
	head[from] = cnt++;

	swap( from, to );

	edge[cnt].from = from;
	edge[cnt].to = to;
	edge[cnt].cap =  0;
	edge[cnt].next = head[from];
	head[from] = cnt++;
}

void addedge2( int from, int to, int cap )
{
	edge2[cnt2].from = from;
	edge2[cnt2].to = to;
	edge2[cnt2].cap = cap;
	edge2[cnt2].next = head2[from];
	head2[from] = cnt2++;
}

bool bfs()
{
	memset( level, -1, sizeof level );
	queue<int> q;
	while(!q.empty())
		q.pop();

	level[src] = 0;
	q.push( src );

	while(!q.empty())
	{
		int u = q.front();
		q.pop();

		for(int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].to;
			if(edge[i].cap > 0 && level[v] == -1)
			{
				level[v] = level[u] + 1;
				q.push( v );
				if(v == des) return level[des] != -1;
			}
		}
	}
	return level[des] != -1;
}

int dfs( int u, int f )
{
	if(u == des) return f;
	int tem;
	for(int i = head[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].to;
		if(edge[i].cap > 0 && level[v] == level[u] + 1)
		{
			tem = dfs( v, min( f, edge[i].cap ) );
			if(tem > 0)
			{
				edge[i].cap -= tem;
				edge[i ^ 1].cap += tem;
				return tem;
			}
		}
	}
	level[u] = -1;
	return 0;
}

int Dinic()
{
	int ans = 0, tem = 0;
	while(bfs())
	{
		tem = dfs( src, INF );
		if(tem > 0)
			ans += tem;
	}
	return ans;
}

int main()
{
	int n, m;
	while(cin >> n >> m)
	{
		cnt = cnt2 = 0;
		src = 1; des = n;
		memset( head, -1, sizeof head );
		memset( head2, -1, sizeof head2 );
		memset( dis1, INF, sizeof dis1 );
		memset( dis2, INF, sizeof dis2 );

		int a, b, c;
		for(int i = 1; i <= m; i++)
		{
			scanf( "%d%d%d",&a,&b,&c);
			addedge2( a, b, c );
			addedge2( b, a, c );
		}

		SPFA( dis1, 1, n );
		SPFA( dis2, n, n );

		for(int i = 1; i <= n; i++) //重构图
		{
			for(int j = head2[i]; j != -1; j = edge2[j].next)
			{
				int v = edge2[j].to;
				if(dis1[i] + edge2[j].cap + dis2[v] == dis1[n])
				{
					addedge( i, v, 1 );
					edge2[j].cap = 1;
				}
				else
				{
					edge2[j].cap = INF;
				}
			}
		}

		memset( dis1, INF, sizeof dis1 );
		SPFA(dis1, 1, n );
		cout << Dinic()<<" " << m-dis1[n]<<endl;
	}
	return 0;
}

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

时间: 2024-07-30 08:27:28

解题报告 之 HDU5294 Tricks Device的相关文章

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 Tricks Device(最短路 + 最大流)

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

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time

hdu 1541 Stars 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 题目意思:有 N 颗星星,每颗星星都有各自的等级.给出每颗星星的坐标(x, y),它的等级由所有比它低层(或者同层)的或者在它左手边的星星数决定.计算出每个等级(0 ~ n-1)的星星各有多少颗. 我只能说,题目换了一下就不会变通了,泪~~~~ 星星的分布是不是很像树状数组呢~~~没错,就是树状数组题来滴! 按照题目输入,当前星星与后面的星星没有关系.所以只要把 x 之前的横坐标加起来就可以了

【百度之星2014~初赛(第二轮)解题报告】Chess

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~初赛(第二轮)解题报告]Chess>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=667 前言 最近要毕业了,有半年没做

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh童鞋的提醒. 勘误2:第7题在推断连通的时候条件写错了,后两个if条件中是应该是<=12 落了一个等于号.正确答案应为116. 1.煤球数目 有一堆煤球.堆成三角棱锥形.详细: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形). -. 假设一共

[noip2011]铺地毯(carpet)解题报告

最近在写noip2011的题,备战noip,先给自己加个油! 下面是noip2011的试题和自己的解题报告,希望对大家有帮助,题目1如下 1.铺地毯(carpet.cpp/c/pas) [问题描述]为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有n 张地毯,编号从1 到n.现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上.地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的

ACdream 1203 - KIDx&#39;s Triangle(解题报告)

KIDx's Triangle Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description One day, KIDx solved a math problem for middle students in seconds! And than he created this problem. N

解题报告 之 CodeForces 91B Queue

解题报告 之 CodeForces 91B Queue Description There are n walruses standing in a queue in an airport. They are numbered starting from the queue's tail: the 1-st walrus stands at the end of the queue and the n-th walrus stands at the beginning of the queue.