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

    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
    ",wto[ans.se << 1]);
    		puts("1");
    		printf("%d",ans.se + 1);
    	} else {
    		printf("%d
    ",res);
    		puts("2");
    		printf("%d %d" , ans.fi + 1 , ans.se + 1);
    	}
    }
    
  • 相关阅读:
    [ jquery 选择器 :hidden ] 此方法选取匹配所有不可见元素,或者type为hidden的元素
    剑指 Offer 03. 数组中重复的数字 哈希
    LeetCode 1736. 替换隐藏数字得到的最晚时间 贪心
    Leetcode 1552. 两球之间的磁力 二分
    Leetcode 88. 合并两个有序数组 双指针
    LeetCode 1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
    LeetCode 1743. 相邻元素对还原数组 哈希
    LeetCode 1745. 回文串分割 IV dp
    剑指 Offer 47. 礼物的最大价值 dp
    剑指 Offer 33. 二叉搜索树的后序遍历序列 树的遍历
  • 原文地址:https://www.cnblogs.com/yijan/p/cf700c.html
Copyright © 2011-2022 走看看