zoukankan      html  css  js  c++  java
  • HDU 4005 The war(边双连通)

    题意

    ​ 给定一张 (n) 个点 (m) 条边的无向连通图,加入一条边,使得图中权值最小的桥权值最大,如果能使图中没有桥则输出 (-1)

    思路

    ​ 先对原图边双缩点,然后变成了一棵树。在树上加一条边等价于使一条路径上的边都不是桥,那么原题转化为在树上删一条路径,使得最小的边最大。固定一条最小的边之后模拟即可。

    代码

    #include<bits/stdc++.h>
    #define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
    #define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
    template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
    template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
    typedef long long ll;
    const int N = 10005;
    const int M = 100005;
    
    template<const int N, const int M, typename T> struct Linked_List
    {
    	int head[N], nxt[M], tot; T to[M];
    	Linked_List() {clear();}
    	T &operator [](const int x) {return to[x];}
    	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
    	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
    	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
    };
    
    struct edge {int to, cost;};
    Linked_List<N, M << 1, edge> G;
    Linked_List<N, N << 1, edge> T;
    
    int dfn[N], low[N], stk[N], bel[N], dfn_idx, tp, bcc;
    int miner[N], son[N];
    int n, m;
    
    void tarjan(int u, int fa_e)
    {
    	dfn[u] = low[u] = ++dfn_idx, stk[++tp] = u;
    	EOR(i, G, u)
    	{
    		if(i == (fa_e ^ 1)) continue;
    		int v = G[i].to;
    		if(!dfn[v]) tarjan(v, i), chk_min(low[u], low[v]);
    		else if(dfn[v] < dfn[u]) chk_min(low[u], dfn[v]);
    	}
    	if(dfn[u] == low[u])
    	{
    		bcc++;
    		do bel[stk[tp]] = bcc; while(stk[tp--] != u);
    	}
    }
    
    void dfs(int u, int f)
    {
    	miner[u] = 2e9, son[u] = 0;
    	EOR(i, T, u)
    	{
    		int v = T[i].to, w = T[i].cost;
    		if(v == f) continue;
    		dfs(v, u);
    		if(chk_min(miner[u], miner[v])) son[u] = v;
    		if(chk_min(miner[u], w)) son[u] = v;
    	}
    }
    
    int redfs(int u, int f)
    {
    	if(!son[u]) return 2e9;
    	int res = redfs(son[u], u);
    	EOR(i, T, u)
    	{
    		int v = T[i].to, w = T[i].cost;
    		if(v == f || v == son[u]) continue;
    		chk_min(res, miner[v]);
    		chk_min(res, w);
    	}
    	return res;
    }
    
    int main()
    {
    	while(~scanf("%d%d", &n, &m))
    	{
    		G.tot = T.tot = 0;
    		FOR(i, 1, n) G.head[i] = T.head[i] = -1;
    		FOR(i, 1, n) dfn[i] = 0;
    		bcc = dfn_idx = 0;
    
    		FOR(i, 1, m)
    		{
    			int u, v, w;
    			scanf("%d%d%d", &u, &v, &w);
    			G.add(u, (edge){v, w}), G.add(v, (edge){u, w});
    		}
    
    		tarjan(1, -1);
    
    		int s, t, mi = 2e9;
    		FOR(u, 1, n) EOR(i, G, u)
    		{
    			int v = G[i].to, w = G[i].cost;
    			if(bel[u] < bel[v])
    			{
    				if(chk_min(mi, w)) s = bel[u], t = bel[v];
    				T.add(bel[u], (edge){bel[v], w}), T.add(bel[v], (edge){bel[u], w});
    			}
    		}
    
    		dfs(s, t), dfs(t, s);
    		int res = std::min(redfs(s, t), redfs(t, s));
    		printf("%d
    ", (res > 1e9 ? -1 : res));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    vue使用talkIngData统计
    vue项目中使用百度统计
    vue的指令修饰符
    提问:
    整理心情再投入下一个阶段
    CSS写三角形
    单行文本和多行文本超出隐藏
    清除浮动的方法
    用JS表示斐波拉契数列
    vue中使用动态挂载和懒加载,实现点击导航栏菜单弹出不同弹框
  • 原文地址:https://www.cnblogs.com/Paulliant/p/12048559.html
Copyright © 2011-2022 走看看