zoukankan      html  css  js  c++  java
  • CF700C Break Up

    statement

    给你一个 (n) 个点 (m) 条边的无向图,边有权值,要求你删去最多两条边,使得 (s)(t) 不连通,且删去的边权值和最小。

    Hints

    (2le nle 1000)(0le m le 30000)

    solution

    首先考虑删除一条边的情况,必定是有一条从 (s)(t) 的所有路径中,都经过的一条边,随便找一条路径枚举即可,时间复杂度 (mathcal O (n imes m))

    两条路径的情况就是把一条边删去后,又出现了一条如上述的边,而直接枚举两条边的复杂度是 (mathcal O (m ^ 3)) 的,通过 tarjan 算法判桥可以做到 (mathcal O (m ^ 2))

    很容易发现,这样枚举是有完全不可能合法的方案的,运用人类智慧,发现在同一条 (s ightarrow t) 的路径上必定有一条边是会被删去的。

    所以直接先拉出任意一条路径,直接暴力枚举即可,时间复杂度 (mathcal O (n imes m))

    struct Lst {
    	int dir, nxt, w;
    	Lst() {}
    	Lst(int _d, int _n, int _w) : dir(_d), nxt(_n), w(_w) {}
    } E[M << 1];
    int G[N], cnt = 1;
    inline void Add(int u, int v, int w) {E[++cnt] = Lst(v, G[u], w), G[u] = cnt;}
    int n, m, s, t, ban, dfn[N], ord, brg[M], vis[M], vt[M], lst[N], res = 2e9 + 1;
    vector<int> pth;
    void path(int u) {
    	vis[u] = 1; if(u == t) return ;
    	for(register int i=G[u], v; i; i=E[i].nxt) if(i != ban && i != (ban ^ 1)) {
    		v = E[i].dir; 
    		if(vis[v]) continue ;
    		lst[v] = i, path(v);
    	}
    }
    int tarjan(int u) {
    	int low = dfn[u] = ++ord, lowv;
    	for(register int i=G[u], v; i; i=E[i].nxt) if(!vt[i]) {
    		v = E[i].dir, vt[i] = vt[i ^ 1] = 1;
    		if(!dfn[v]) {
    			low = min(low, lowv = tarjan(v));
    			if(lowv > dfn[u]) {
    				brg[i >> 1] = 1;
    			}
    		} else if(dfn[v] < dfn[u]) low = min(low, dfn[v]);
    	}
    	return low;
    }
    int ansl, ansr;
    int main() {
    	scanf("%d%d%d%d", &n, &m, &s, &t);
    	forn(i,1,m) {
    		static int u, v, w;
    		scanf("%d%d%d", &u, &v, &w);
    		Add(u, v, w), Add(v, u, w);
    	}
    	ban = 1e9, path(s);
    	if(!vis[t]) return printf("0
    0
    ") & 0;
    	int tmp = t;
    	while(tmp != s) pth.push_back(lst[tmp]), tmp = E[lst[tmp] ^ 1].dir; 
    	ansl = ansr = -1;
    	rep(i,0,pth.size()) {
    		ban = pth[i], ord = 0;
    		memset(dfn, 0, sizeof dfn);
    		memset(brg, 0, sizeof brg);
    		memset(vis, 0, sizeof vis);
    		memset(lst, 0, sizeof lst);
    		memset(vt, 0, sizeof vt);
    		vt[pth[i]] = vt[pth[i] ^ 1] = 1;
    		path(s);
    		if(!vis[t]) {
    			if(res > E[pth[i]].w) res = E[pth[i]].w, ansl = pth[i], ansr = -1;
    		} else {
    			tarjan(s), tmp = t;
    			while(tmp != s) {
    				int e = lst[tmp];
    				if(brg[e >> 1]) if(res > E[pth[i]].w + E[e].w)
    					res = E[pth[i]].w + E[e].w, ansl = pth[i], ansr = e;
    				tmp = E[e ^ 1].dir;
    			} 
    		}
    	}
    	if(res == 2e9 + 1) return puts("-1") & 0;
    	if(ansr == -1) {
    		printf("%d
    1
    ", res);
    		printf("%d
    ", ansl >> 1);
    	} else {
    		printf("%d
    2
    ", res);
    		printf("%d %d
    ", ansl >> 1, ansr >> 1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    团队选题报告
    第二次结对作业
    高级软件工程团队第一次作业
    第一次结队作业
    高级软件工程第二次作业
    高级软件工程第一次作业
    洛谷 题解 2165 [AHOI2009]飞行棋
    洛谷 题解 P1684 考验
    洛谷 题解 P4613 【[COCI2017-2018#5] Olivander】
    洛谷 题解 P5534 【【XR-3】等差数列】
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/15234148.html
Copyright © 2011-2022 走看看