[hdu 6166 Senior Pan]Dijkstra+概率随机
分类:Dijkstra
probability
data structure
1. 题目链接
2. 题意描述
有一个
n
个顶点
数据范围:
1≤数据组数≤5
,
1≤n,m≤100000
,
2≤K≤n
,
1≤边权≤100000
。
3. 解题思路
方法一:假设最终的答案对应的两个端点为
s,t
, 将K个点分成两半,那么,有四种情况:
1.
s,t
在前一半;
2.
s,t
在后一半;
3.
s
在第一半
4.
t
在第一半
如果是Solution 3或者Solution 4, 只需要将一个超级源点连接所有前一半的点,边权为0,跑一遍Dijkstra。就可以求出前一半点集到后一半点集的最短路,这样就可以得到答案了。
如果是Solution 1或者Solution 2, 按照上面的做法是得不到答案的。
这样,一次Dijkstra跑出答案的概率为
12
,那么重复
x
次,成功的概率为
这题,随机技巧性很强。
方法二:只需要一次Dijkstra就可以了。选一个超级源点,并连接所有
K
个点,权值为0。Dijkstra算法中,每次枚举边的同时,顺便更新答案就好了。感觉这个挺容易写错的。
Tips:将超级源点连接到点集
V ,并不一定非得新建一个顶点,只需要将点集 V <script type="math/tex" id="MathJax-Element-22">V</script>中所有点一起放入队列,并将到该点的最短路径置为0就好了。4. 实现代码
/**方法一**/ #include <set> #include <map> #include <queue> #include <stack> #include <ctime> #include <cmath> #include <cctype> #include <cstdio> #include <string> #include <cstring> #include <cassert> #include <cstdlib> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef long double LB; typedef unsigned int uint; typedef unsigned long long ULL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; typedef pair<LB, LB> PLB; typedef vector<int> VI; const int INF = 0x3f3f3f3f; const LL INFL = 0x3f3f3f3f3f3f3f3fLL; const long double PI = acos(-1.0); const long double eps = 1e-4; void debug() { cout << endl; } template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); } template<typename T> inline void umax(T &a, T b) { a = max(a, b); } template<typename T> inline void umin(T &a, T b) { a = min(a, b); } template <typename T> inline bool scan_d (T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; //EOF while (c != '-' && (c < '0' || c > '9') ) if((c = getchar()) == EOF) return 0; sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template<typename T> void print(T x) { static char s[33], *s1; s1 = s; if (!x) *s1++ = '0'; if (x < 0) putchar('-'), x = -x; while(x) *s1++ = (x % 10 + '0'), x /= 10; while(s1-- != s) putchar(*s1); } template<typename T> void println(T x) { print(x); putchar('\n'); } template<typename T> T randIntv(T a, T b) { return rand() % (b - a + 1) + a; } /*[a, b]*/ const int MAXN = 100005; const int MAXE = 100005; int T, n, m, K; int a[MAXN]; LL ans; template<class T> struct Dijkstra { struct Edge { T w; int v, nxt; } E[MAXE << 1]; typedef pair<T, int> QNode; int Head[MAXN], erear; T d[MAXN], INF; void init() { erear = 0; memset(Head, -1, sizeof(Head)); } void add_edge(int u, int v, T w) { E[erear].v = v; E[erear].w = w; E[erear].nxt = Head[u]; Head[u] = erear++; } T run() { memset(d, 0x3f, sizeof(d)); INF = d[0]; priority_queue<QNode, vector<QNode>, greater<QNode> >Q; for(int i = 1; i <= K / 2; ++i) Q.push(QNode(0, a[i])); d[a[i]] = 0; while(!Q.empty()) { QNode ftp = Q.top(); Q.pop(); int u = ftp.second; if(ftp.first != d[u]) continue; for(int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; T w = E[i].w; if(d[u] + w < d[v]) { d[v] = d[u] + w; Q.push(QNode(d[v], v)); } } } T ret = INF; for(int i = K / 2 + 1; i <= K; ++i) umin(ret, d[a[i]]); return ret; } }; Dijkstra<LL> dij; int main() { #ifdef ___LOCAL_WONZY___ freopen ("input.txt", "r", stdin); #endif // ___LOCAL_WONZY___ int cas = 0, u, v, w; scan_d(T); while(T --) { scan_d(n), scan_d(m); dij.init(); for(int i = 1; i <= m; ++i) { scan_d(u), scan_d(v), scan_d(w); dij.add_edge(u, v, w); } scan_d(K); for(int i = 1; i <= K; ++i) { scan_d(a[i]); } ans = INFL; int times = 20; while(times --) { random_shuffle(a + 1, a + K + 1); // for_each(a + 1, a + K + 1, [](int item) { cout << item << " "; }); puts(""); umin(ans, dij.run()); } printf("Case #%d: %lld\n", ++cas, ans); } #ifdef ___LOCAL_WONZY___ cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl; #endif // ___LOCAL_WONZY___ return 0; }
/**方法二**/ #include <set> #include <map> #include <queue> #include <stack> #include <ctime> #include <cmath> #include <cctype> #include <cstdio> #include <string> #include <cstring> #include <cassert> #include <cstdlib> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; typedef long double LB; typedef unsigned int uint; typedef unsigned long long ULL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; typedef pair<LB, LB> PLB; typedef vector<int> VI; const int INF = 0x3f3f3f3f; const LL INFL = 0x3f3f3f3f3f3f3f3fLL; const long double PI = acos(-1.0); const long double eps = 1e-4; void debug() { cout << endl; } template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); } template<typename T> inline void umax(T &a, T b) { a = max(a, b); } template<typename T> inline void umin(T &a, T b) { a = min(a, b); } template <typename T> inline bool scan_d (T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; //EOF while (c != '-' && (c < '0' || c > '9') ) if((c = getchar()) == EOF) return 0; sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template<typename T> void print(T x) { static char s[33], *s1; s1 = s; if (!x) *s1++ = '0'; if (x < 0) putchar('-'), x = -x; while(x) *s1++ = (x % 10 + '0'), x /= 10; while(s1-- != s) putchar(*s1); } template<typename T> void println(T x) { print(x); putchar('\n'); } template<typename T> T randIntv(T a, T b) { return rand() % (b - a + 1) + a; } /*[a, b]*/ const int MAXN = 100005; const int MAXE = 100005; int T, n, m, K; int a[MAXN]; LL ans; bool flag[MAXN]; template<class T> struct Dijkstra { struct Edge { T w; int v, nxt; } E[MAXE << 1]; typedef tuple<T, int, int> QNode; int Head[MAXN], erear; T d[MAXN], INF; void init() { erear = 0; memset(Head, -1, sizeof(Head)); } void add_edge(int u, int v, T w) { E[erear].v = v; E[erear].w = w; E[erear].nxt = Head[u]; Head[u] = erear++; } T run() { memset(d, 0x3f, sizeof(d)); INF = d[0]; priority_queue<QNode, vector<QNode>, greater<QNode> >Q; for(int i = 1; i <= K; ++i) Q.push(QNode(0, a[i], a[i])), d[a[i]] = 0; T ret = INF; T cost; int u, fu; while(!Q.empty()) { tie(cost, u, fu) = Q.top(); Q.pop(); if(cost != d[u]) continue; for(int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; T w = E[i].w; if(flag[v] && v != fu) umin(ret, d[u] + w); /**注意v!=fu的条件**/ if(d[u] + w < d[v]) { d[v] = d[u] + w; Q.push(QNode(d[v], v, flag[v] ? v : fu)); } } } return ret; } }; Dijkstra<LL> dij; int main() { #ifdef ___LOCAL_WONZY___ freopen ("input.txt", "r", stdin); #endif // ___LOCAL_WONZY___ int cas = 0, u, v, w; scan_d(T); while(T --) { scan_d(n), scan_d(m); dij.init(); for(int i = 1; i <= m; ++i) { scan_d(u), scan_d(v), scan_d(w); dij.add_edge(u, v, w); } scan_d(K); memset(flag, false, sizeof(flag)); for(int i = 1; i <= K; ++i) { scan_d(a[i]); flag[a[i]] = true; } ans = dij.run(); printf("Case #%d: %lld\n", ++cas, ans); } #ifdef ___LOCAL_WONZY___ cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl; #endif // ___LOCAL_WONZY___ return 0; }