Wannafly挑战赛2D Delete (最短路好题)

大意: 给定DAG, 给定点$S,T$, 每次询问给出点$x$, 求删除$x$后的$S->T$的最短路, 询问之间独立.

删除点$x$的最短路一定要经过一条边$(u,v)$, 满足$u$拓扑序在$x$前, $v$拓扑序在$x$后. (对于拓扑序相同的点不会有影响)

这样可以枚举每一条边, 用线段树维护删除每个点的答案.

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#include <unordered_map>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;})
using namespace std;
typedef long long ll;

#ifdef ONLINE_JUDGE
const int N = 1e6+10;
#else
const int N = 999;
#endif

const ll INF = 0x3f3f3f3f3f3f3f3f;
int n,m,S,T,deg[N],a[N],vis[N],no[N];
struct _ {int to,w;};
vector<_> g[N], gg[N];
ll d1[N], d2[N], tr[N<<2], ans[N];
queue<int> q;

void topo() {
	REP(i,1,n) if (!deg[i]) q.push(i);
	int clk = 0;
	while (q.size()) {
		int u = q.front(); q.pop();
		a[u] = ++clk, no[clk] = u;
		for (auto &e:g[u]) if (!--deg[e.to]) q.push(e.to);
	}
}
struct __ {
	int u;
	ll w;
	bool operator < (const __ &rhs) const {
		return w>rhs.w;
	}
};

void DP(ll d[], vector<_> g[], int s) {
	memset(d,0x3f,sizeof d1);
	memset(vis,0,sizeof vis);
	priority_queue<__> q;
	q.push({s,d[s]=0});
	while (q.size()) {
		int u = q.top().u; q.pop();
		if (vis[u]) continue;
		vis[u] = 1;
		for (auto &e:g[u]) {
			ll dd = d[u]+e.w;
			if (dd<d[e.to]) q.push({e.to,d[e.to]=dd});
		}
	}
}

void update(int o, int l, int r, int ql, int qr, ll v) {
	if (ql<=l&&r<=qr) return tr[o]=min(tr[o],v),void();
	if (mid>=ql) update(ls,ql,qr,v);
	if (mid<qr) update(rs,ql,qr,v);
}
void dfs(int o, int l, int r) {
	if (l==r) {
		if (d1[no[l]]==INF||d2[no[l]]==INF) ans[no[l]]=d1[T];
		else ans[no[l]]=tr[o];
	}
	else {
		tr[lc]=min(tr[lc],tr[o]);
		tr[rc]=min(tr[rc],tr[o]);
		dfs(ls),dfs(rs);
	}
}

int main() {
	scanf("%d%d%d%d", &n, &m, &S, &T);
	REP(i,1,m) {
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		g[x].pb({y,z}),++deg[y];
		gg[y].pb({x,z});
	}
	topo();
	DP(d2,gg,T);
	DP(d1,g,S);
	memset(tr,0x3f,sizeof tr);
	REP(i,1,n) {
		for (auto e:g[i]) {
			if (a[e.to]!=a[i]+1&&d1[i]!=INF&&d2[e.to]!=INF) {
				update(1,1,n,a[i]+1,a[e.to]-1,e.w+d1[i]+d2[e.to]);
			}
		}
	}
	dfs(1,1,n);
	int q;
	scanf("%d", &q);
	while (q--) {
		int t;
		scanf("%d", &t);
		printf("%lld\n",ans[t]);
	}
}

原文地址:https://www.cnblogs.com/uid001/p/10986812.html

时间: 2024-10-11 18:42:44

Wannafly挑战赛2D Delete (最短路好题)的相关文章

Wannafly挑战赛24-A-石子游戏--【思维题】

链接:https://www.nowcoder.com/acm/contest/186/A 来源:牛客网 石子游戏 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 Alice和Bob在玩游戏,他们面前有n堆石子,对于这些石子他们可以轮流进行一些操作,不能进行下去的人则输掉这局游戏. 可以进行两种操作: 1. 把石子数为奇数的一堆石子分为两堆正整数个石子 2. 把两堆石子数为偶数的石子合并

Wannafly挑战赛3

Wannafly挑战赛3 A    珂朵莉 B    遇见 水题 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a

【Wannafly挑战赛4】F 线路规划 倍增+Kruskal+归并

[Wannafly挑战赛4]F 线路规划 题目描述 Q国的监察院是一个神秘的组织.这个组织掌握了整个帝国的地下力量,监察着Q国的每一个人.监察院一共有N个成员,每一个成员都有且仅有1个直接上司,而他只听从其上直接司的命令.其中1号成员是监察院的院长,这个庞然大物的主人.由于时代的进步,监察院议会决定升级组织的旧式通信器,安装最新的反侦测通信器.他们拿出了M组线路方案,其中第i组线路方案可以用一个四元组(x[i].y[i].k[i].w[i])描述,表示第x[i]号成员可以安装与y[i]号成员的直

牛客网 Wannafly挑战赛8 C-小C打比赛 (状压DP)

小C现在要参加一场wannafly挑战赛,一场挑战赛一共有n道题,一共有m分钟. 对于第i道题,小C解决它需要恰好j分钟的概率是pi,j. 小C每次会选择某一道没做完的题,然后把它解决(不能中途放弃),之后再决策下一道要做的题是哪道. 求小C在最优策略下,期望能做出几道题. 输入描述: 第一行两个正整数n,m接下来一共n行,每行有m个小数,第i行的第j个小数表示p i,j (这里假设不存在0分钟A题的dalao). 输出描述: 输出一个小数,表示期望能做出几道题,保留小数点后五位. 示例1 输入

HDU 5521.Meeting 最短路模板题

Meeting Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 3361    Accepted Submission(s): 1073 Problem Description Bessie and her friend Elsie decide to have a meeting. However, after Farmer Jo

poj1511/zoj2008 Invitation Cards(最短路模板题)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Invitation Cards Time Limit: 5 Seconds      Memory Limit: 65536 KB In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fa

最短路入门题

http://acm.hdu.edu.cn/showproblem.php?pid=2544 DJ #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #define N 1000001 using namespace std; int map[101][101]; int n,m; int v[101],

kuangbin专题四 : 最短路 I 题 Arbitrage

kuangbin专题四 : 最短路 I 题  Arbitrage POJ 2240 Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound,

Wannafly挑战赛11 D 白兔的字符串 Hash

Wannafly挑战赛11 D   白兔的字符串 白兔有一个字符串T.白云有若干个字符串S1,S2..Sn. 白兔想知道,对于白云的每一个字符串,它有多少个子串是和T循环同构的. 提示:对于一个字符串a,每次把a的第一个字符移动到最后一个,如果操作若干次后能够得到字符串b,则a和b循环同构. 所有字符都是小写英文字母 输入描述: 第一行一个字符串T(|T|<=10^6)第二行一个正整数n (n<=1000)接下来n行为S1~Sn (|S1|+|S2|+…+|Sn|<=10^7),max(