Break up CF700C 首先考虑只能删一条边的做法,我们可以找出所有的桥,然后随便跑一条 S 到 T 路径,如果这条路径上有桥就说明可以,否则不行 发现这个做法其实是 O(M) 的 那么可以先随
Break up
CF700C
首先考虑只能删一条边的做法,我们可以找出所有的桥,然后随便跑一条 S 到 T 路径,如果这条路径上有桥就说明可以,否则不行
发现这个做法其实是 O(M) 的
那么可以先随便找一条 N 到 M 的路径,分别尝试删这条路径上的边再套上面做法就好了。
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<vector> #include<queue> #include<stack> using namespace std; //#define int long long #define MAXN 3016 #define pb push_back #define pii pair<int,int> #define fi first #define se second #define mp make_pair #define inf 0x3f3f3f3f #define cmx( a , b ) a = max( a , b ) #define cmn( a , b ) a = min( a , b ) int n , m , s , t; int head[MAXN] , nex[MAXN * 50] , to[MAXN * 50] , wto[MAXN * 50] , ecn = -1; void ade( int u , int v , int w ) { nex[++ecn] = head[u] , to[ecn] = v , wto[ecn] = w , head[u] = ecn; } int vis[MAXN] , pre[MAXN]; int fuck = 0x7f7f7f7f; bool findpath( int u ) { if( u == t ) return true; vis[u] = 1; for( int i = head[u] ; ~i ; i = nex[i] ) { if( i == fuck || i == ( fuck ^ 1 ) ) continue; int v = to[i]; if( vis[v] ) continue; pre[v] = i ^ 1; if( findpath( v ) ) return true; } return false; } int clo; int dfn[MAXN] , low[MAXN]; int cut[MAXN * 50] , done[MAXN]; int use[MAXN * 50]; void tarjan( int u ) { done[u] = 1; dfn[u] = low[u] = ++ clo; for( int i = head[u] ; ~i ; i = nex[i] ) { if( use[i] ) continue; use[i] = use[i ^ 1] = 1; if( i == fuck || i == ( fuck ^ 1 ) ) continue; int v = to[i]; if( !dfn[v] ) { tarjan( v ); low[u] = min( low[u] , low[v] ); if( low[v] > dfn[u] ) cut[i] = cut[i ^ 1] = true; } else if( done[v] == 1 ) low[u] = min( low[u] , dfn[v] ); } done[u] = 2; } vector<int> eds; pii ans; int main() { memset( head , -1 , sizeof head ); cin >> n >> m >> s >> t; for( int i = 1 , u , v , w ; i <= m ; ++ i ) { scanf("%d%d%d",&u,&v,&w); ade( u , v , w ) , ade( v , u , w ); } if( !findpath( s ) ) return puts("0") , puts("0") , 0; int c = t; while( c != s ) eds.pb( pre[c] ) , c = to[pre[c]]; int res = 0x7f7f7f7f; for( int i = 0 ; i < eds.size() ; ++ i ) { fuck = eds[i]; memset( cut , 0 , sizeof cut ); memset( done , 0 , sizeof done ); memset( use , 0 , sizeof use ); memset( dfn , 0 , sizeof dfn ); memset( low , 0 , sizeof low ); clo = 0; tarjan( s ); memset( vis , 0 , sizeof vis ); if( ! findpath( s ) ) { if( res > wto[fuck] ) res = wto[fuck] , ans = mp( 0 , fuck >> 1 ); continue; } c = t; while( c != s ) { if( cut[pre[c]] ) if( res > wto[fuck] + wto[pre[c]] ) res = wto[fuck] + wto[pre[c]] , ans = mp( fuck >> 1 , pre[c] >> 1 ); c = to[pre[c]]; } } if( res == 0x7f7f7f7f ) return puts("-1") , 0; if( ! ans.fi ) { printf("%d\n",wto[ans.se << 1]); puts("1"); printf("%d",ans.se + 1); } else { printf("%d\n",res); puts("2"); printf("%d %d" , ans.fi + 1 , ans.se + 1); } }