Codeforces Round #364 (Div. 2) F. Break Up(tarjan+暴力)

F. Break Up

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Again, there are hard times in Berland! Many towns have such tensions that even civil war is possible.

There are n towns in Reberland, some pairs of which connected by two-way roads. It is not guaranteed that it is possible to reach one town from any other town using these roads.

Towns s and t announce the final break of any relationship and intend to rule out the possibility of moving between them by the roads. Now possibly it is needed to close several roads so that moving from s to t using roads becomes impossible. Each town agrees to spend money on closing no more than one road, therefore, the total number of closed roads will be no more than two.

Help them find set of no more than two roads such that there will be no way between s and t after closing these roads. For each road the budget required for its closure was estimated. Among all sets find such that the total budget for the closure of a set of roads is minimum.

Input

The first line of the input contains two integers n and m (2 ≤ n ≤ 1000, 0 ≤ m ≤ 30 000) — the number of towns in Berland and the number of roads.

The second line contains integers s and t (1 ≤ s, t ≤ ns ≠ t) — indices of towns which break up the relationships.

Then follow m lines, each of them contains three integers x iy i and w i (1 ≤ x i, y i ≤ n, 1 ≤ w i ≤ 109) — indices of towns connected by the i-th road, and the budget on its closure.

All roads are bidirectional. It is allowed that the pair of towns is connected by more than one road. Roads that connect the city to itself are allowed.

Output

In the first line print the minimum budget required to break up the relations between s and t, if it is allowed to close no more than two roads.

In the second line print the value c (0 ≤ c ≤ 2) — the number of roads to be closed in the found solution.

In the third line print in any order c diverse integers from 1 to m — indices of closed roads. Consider that the roads are numbered from 1 to m in the order they appear in the input.

If it is impossible to make towns s and t disconnected by removing no more than 2 roads, the output should contain a single line -1.

If there are several possible answers, you may print any of them.

Examples

input

Copy

6 7
1 6
2 1 6
2 3 5
3 4 9
4 6 4
4 6 5
4 5 1
3 1 3

output

Copy

8
2
2 7

input

Copy

6 7
1 6
2 3 1
1 2 2
1 3 3
4 5 4
3 6 5
4 6 6
1 5 7

output

Copy

9
2
4 5

input

Copy

5 4
1 5
2 1 3
3 2 1
3 4 4
4 5 2

output

Copy

1
1
2

input

Copy

2 3
1 2
1 2 734458840
1 2 817380027
1 2 304764803

output

Copy

-1

题目大意:

N(1<=N<=1e3)个点,M(1<=M<=4e3)条边的带边权无向图,删除一条边的代价为该边边权,你要找到一个最小代价,使得S和T不连通,输出代价、删除的边数、边的编号,删除的数量要<=2。

没想到怎么写T_T,好不容易看懂做法,还是个码农题,感觉很多暴力的图论题都和删边删点有关吧。

解法:

删除边数为0:S与T一定不连通,判一下就好。

删除边数为1:S与T之间有一条割边,找到该割边的最小权值。

删除边数为2:S到T只有两条路径,求两路径的最小值之和。

0是单独判的,1和2都得求,因为可能删除两条边比删除一条边更优。我们先找到一条S到T的路径,假设该路径为L1,枚举删除L1上的边,从S到T记录第二条路径L2,如果这时候无法从S到T,那么删除的边一定是割边,更新下答案;否则求一下整张图的割边,如果割边存在于L2中,那就说明当前L1中枚举删除的边与L2中的一条割边可以使S无法到达T,若不存在割边,此时无解。

Accepted code

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 1e3 + 100;
const int M = 3e4 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }

vector <pir> G[N << 1];
vector <int> g;
int dfn[N], low[N], n, m, cnt;
int val[M], sp, tp;
int edge[M], res;
bool vis[N], cut[M];
int ID[5];
ll ans;

bool path(int x) {   // 找到L1路径,同时判断S与T是否连联通
	if (x == tp)
		return true;
	vis[x] = true;
	for (auto it : G[x]) {
		int v = it.first, id = it.second;
		if (!vis[v] && path(v)) {
			edge[++res] = id;
			return true;
		}
	}
	return false;
}
bool dfs(int x, int no) {   // 找到L2路径,no表示当前删除的边
	if (x == tp)
		return true;
	vis[x] = true;
	for (auto it : G[x]) {
		int v = it.first;
		int id = it.second;
		if (id != no && !vis[v] && dfs(v, no)) {
			g.push_back(id);
			return true;
		}
	}
	return false;
}
void tarjan(int x, int fa, int no) {  // 求割边,no表示当前删除的边,fa表示上一次走的边编号
	dfn[x] = low[x] = ++cnt;
	for (auto it : G[x]) {
		int v = it.first, id = it.second;
		if (id == fa || id == no)
			continue;
		if (!dfn[v]) {
			tarjan(v, id, no);
			Min(low[x], low[v]);
			if (low[v] > dfn[x])
				cut[id] = true;   // 割边
		}
		else
			Min(low[x], dfn[v]);
	}
}

int main()
{
	cin >> n >> m >> sp >> tp;
	for (int i = 1; i <= m; i++) {
		int u, v;
		sc("%d %d %d", &u, &v, &val[i]);  
		G[u].push_back({ v, i });
		G[v].push_back({ u, i });
	}

	// 找任意一条路径
	if (!path(sp))          // 第一种情况
		printf("0\n0\n"), exit(0);

	// 枚举删除第一条路径的边
	ans = LINF;
	for (int i = 1; i <= res; i++) {
		int ii = edge[i]; // 当前删除的编号
		MEM(vis, 0), g.clear();
		if (!dfs(sp, ii)) {          // 第二种情况,删除该边不连通
			if (val[ii] < ans)
				ans = val[ii], ID[1] = ii, ID[2] = 0;
		}
		else {
			cnt = 0;
			MEM(dfn, 0), MEM(low, 0);
			MEM(cut, 0);
			tarjan(sp, 0, ii);

			// 是否有割边
			for (auto it : g) {
				if (cut[it] && val[it] + val[ii] < ans)
					ans = val[it] + val[ii], ID[1] = ii, ID[2] = it;
			}
		}
	}

	if (ans == LINF)
		printf("-1\n");
	else {
		printf("%d\n", ans);
		if (!ID[2])
			printf("1\n%d\n", ID[1]);
		else
			printf("2\n%d %d\n", ID[1], ID[2]);
	}
	return 0;  // 改数组大小!!!用pair记得改宏定义!!!
}

猜你喜欢

转载自blog.csdn.net/weixin_43851525/article/details/106978911