Codeforces 700C Break Up tarjan求桥

C. 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 tusing 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 ≤ 10000 ≤ 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 xiyi and wi (1 ≤ xi, yi ≤ n1 ≤ wi ≤ 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
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
8
2
2 7
input
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
9
2
4 5
input
5 4
1 5
2 1 3
3 2 1
3 4 4
4 5 2
output
1
1
2
input
2 3
1 2
1 2 734458840
1 2 817380027
1 2 304764803
output
-1



一个无向图,可能有自环和重边,现在要随意删去至多两条边使得s和t不连通,问最小花费是多少。


数据范围较小,可以考虑O(nm)算法。

首先,若s和t不连通,那么花费肯定是0.

否则,我们先随意找出一条s到t的路径。若我们删去一些边满足题目要求,则其中至少一条要删的边在这条路径当中。那么,我们可以枚举路径上每一条边把它删去,若删去之后s与t不连通,则直接用这条边的花费更新答案;否则,我们在删去这条边的图上重复刚才的做法,寻找一条路径并枚举这条路径上的每一条边删去之后是否s与t不连通,如果是则用这两条边的花费更新答案。判断删去边后是否连通可以用tarjan算法找桥来判别。


用到的数组较多,一定要记得数组清零!!!


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=1005,maxk=30005,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const ld pi=acos(-1.0L);
int dfn[maxn],low[maxn],head[maxn];
bool visit[maxn],br[maxk],br1[maxk],use[maxk];
vector<int> path,oit,pa;
int num,ans;

struct Edge {
	int from,to,pre,dist;
};
Edge edge[maxk*2];

void addedge(int from,int to,int dist) {
	edge[num]=(Edge){from,to,head[from],dist};
	head[from]=num++;
	edge[num]=(Edge){to,from,head[to],dist};
	head[to]=num++;
}

bool dfs(int now,int t,int p) {
	if (now==t) return true;
	visit[now]=1;
	for (int i=head[now];i!=-1;i=edge[i].pre) {
		int to=edge[i].to;
		if (p==i/2) continue;
		if (!visit[to]) {
			if (dfs(to,t,p)) {
				if (p==0) path.push_back(i/2); else pa.push_back(i/2);
				return true;
			}
		}
	}
	return false;
}

void tarjan(int now,int fa,int t,int p)
{
    dfn[now]=low[now]=++num;
    for(int i=head[now];i!=-1;i=edge[i].pre) {
        int to=edge[i].to;
        if (i/2==p||use[i/2]) continue;
        use[i/2]=1;
        if(!dfn[to])
        {
            tarjan(to,now,t,p);
            low[now]=min(low[now],low[to]);
            if(low[to]>dfn[now])
                if (t==0) br[i/2]=1; else br1[i/2]=1;
        }
        else if(dfn[to]<dfn[now])
        {
            low[now]=min(low[now],dfn[to]);
        }
    }
}

int main() {
	int n,m,i,j,x,y,d,s,t;
	scanf("%d%d%d%d",&n,&m,&s,&t);
	num=2;memset(head,-1,sizeof(head));
	for (i=1;i<=m;i++) {
		scanf("%d%d%d",&x,&y,&d);
		addedge(x,y,d);
	}
	ans=inf*2;
	mem0(visit);path.clear();
	if (!dfs(s,t,0)) {
		printf("0\n0\n");return 0;
	}
	mem0(br);mem0(dfn);mem0(low);mem0(use);num=0;
	for (i=1;i<=n;i++)
		if (!dfn[i]) tarjan(i,0,0,0);
	int size=path.size();
	for (i=0;i<size;i++) {
		int now=path[i];
		if (br[now]) {
			if (ans>edge[now*2].dist) {
				ans=edge[now*2].dist;
				oit.clear();oit.push_back(now);
			}
		} else {
			pa.clear();mem0(visit);
			if (dfs(s,t,now)) {
				mem0(br1);mem0(dfn);mem0(low);mem0(use);num=0;
				for (j=1;j<=n;j++)
					if (!dfn[j]) tarjan(j,0,1,now);
				int s2=pa.size();
				for (j=0;j<s2;j++)
					if (br1[pa[j]]) 
						if (ans>edge[now*2].dist+edge[pa[j]*2].dist) {
							ans=edge[now*2].dist+edge[pa[j]*2].dist;
							oit.clear();
							oit.push_back(now);oit.push_back(pa[j]);
						}
			}
		}
	}
	if (ans==2*inf) 
		printf("-1\n");
	else {
		printf("%d\n",ans);
		printf("%d\n",oit.size());
		for (j=0;j<oit.size();j++) printf("%d ",oit[j]);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值