hdu4005The war

来源:互联网 发布:mysql if与case性能 编辑:程序博客网 时间:2024/06/05 23:44
思路:
无向图求连通分量。我们首先应该知道,因为加入的边未知,所以我们所求的最小金额就是无论加入的边在图中哪里,我们都可以删除一条边来使它不连通。so我们首先对图求解连通分量,然后缩点,形成一棵树。这时候,我们可以想到,在加入一条未知的边之后会形成一个环,显然最小值的边不是我们的答案,因为这条边有可能就在这个环中,这时候我们就删除不了边了(其他边的值都比这个值大)。
我们仔细想想可以发现:根据题意构造最优路径,一条路径通过以结点u为根的子树时,一定会经过以结点u为根的子树中边权最小的那条边,那么这时候我们除去这条路径后剩下的边权中的最小值就是我们要求的答案了。所以,我们的算法思想就是:递归求解每个结点为根的子树中的最小边和次小边,我们必须保证这里最小边和次小边不可能在一条路径上,然后求次小边中的最小值就是答案了。
// #pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <algorithm>#include <iomanip>#include <sstream>#include <string>#include <stack>#include <queue>#include <deque>#include <vector>#include <map>#include <set>#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <limits.h>// #define DEBUG#ifdef DEBUG#define debug(...) printf( __VA_ARGS__ )#else#define debug(...)#endif#define MEM(x,y) memset(x, y,sizeof x)using namespace std;typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int> ii;const int inf = 1 << 30;const int INF = 0x3f3f3f3f;const int MOD = 1e9 + 7;const int maxn = 10010;const int maxm = 1000010;int cnt, num;int head[maxn], pnt[maxm], nxt[maxm], w[maxm];bool vis[maxm], in[maxn];int n, m;int dfn[maxn], low[maxn], id[maxn];int tol;inline void Init(){cnt = num = tol = 0;MEM(in, false);MEM(head, -1);MEM(dfn, -1);MEM(low, -1);MEM(id, -1);}inline void add(int u,int v,int c){pnt[cnt] = v;nxt[cnt] = head[u];vis[cnt] = false;w[cnt] = c;head[u] = cnt++;pnt[cnt] = u;nxt[cnt] = head[v];vis[cnt] = false;w[cnt] = c;head[v] = cnt++;}int t;stack<int> st;int rec[maxm][3];void Tarjan(int u,int fa){dfn[u] = low[u] = t++;st.push(u);in[u] = true;for (int i = head[u];i != -1;i = nxt[i]){int v = pnt[i];if (vis[i]) continue;vis[i] = vis[i ^ 1] = true;if (dfn[v] == -1){Tarjan(v, u);low[u] = min(low[u], low[v]);if (low[v] > dfn[u]){rec[++tol][0] = u;rec[tol][1] = v;rec[tol][2] = w[i];}}else if (low[u] > dfn[v]){low[u] = dfn[v];}}if (dfn[u] == low[u]){while(true){int v = st.top();st.pop();id[v] = num;if (v == u) break;}num++;}}vector<ii> G[maxn];int ans;int dfs(int u,int fa){int Min = INF, vice_Min = INF, rr = INF;for (int i = 0;i < G[u].size();++i){int v = G[u][i].first, cost = G[u][i].second;if (v == fa) continue;int now = dfs(v, u);if (now < vice_Min) vice_Min = now;if (cost < vice_Min) vice_Min = cost;if (Min > vice_Min) swap(vice_Min, Min);if (Min < rr) rr = Min;}if (ans > vice_Min) ans = vice_Min;return rr;}int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout);while(~scanf("%d%d",&n, &m)){t = 0;Init();for (int i = 1, a, b, c;i <= m;++i){scanf("%d%d%d",&a, &b, &c);add(a, b, c);}for (int i = 1;i <= n;++i)if (dfn[i] == -1) Tarjan(i, -1);for (int i = 0;i <= n;++i)G[i].clear();int a, b, Min = INF;for (int i = 1;i <= tol;++i){int u = rec[i][0], v = rec[i][1], cost = rec[i][2];G[id[u]].push_back(ii(id[v], cost));G[id[v]].push_back(ii(id[u], cost));if (cost < Min){a = id[u],b = id[v];Min = cost;}}ans = INF;dfs(a, b);dfs(b, a);if (ans == INF) printf("-1\n");else printf("%d\n",ans);}return 0;}


0 0
原创粉丝点击