• 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);
    	}
    }
    
  • 相关阅读:
    postgresql查询栅格数据范围(extent)
    raster导入postgres Windows命令
    Python使用XML操作mapnik,实现复杂标注(Multi line text symbolizer)
    Leaflet使用vector tiles 标注label设置
    Leaflet使用vector tiles样式设置
    Leaflet调用geoserver发布的矢量切片
    java 生成透明背景图片
    java 用RGB生成图片动态命名
    POI拆分单元格,并设置拆分后第一个cell的值为空cell的值
    洛谷 P1003 铺地毯 题解
  • 原文地址:https://www.cnblogs.com/yijan/p/cf700c.html
Copyright © 2020-2023  润新知