原题链接|T103481 【模板】割边 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
主要是分享一个数据生成器(生成输入数据,再拿我下面的ac代码跑出输出结果就行,自己debug去,乐):
#include <iostream>
#include <vector>
#include <random>
using namespace std;
int main() {
// 随机数生成器
random_device rd;
mt19937 gen(rd());
int n = 10; // 节点数量
int m = 13; // 边数量
cout << n << " " << m << endl;
// 生成图的边
vector<pair<int, int>> edges;
for (int i = 1; i <= m; i++) {
int u = uniform_int_distribution<int>(1, n)(gen);
int v = uniform_int_distribution<int>(1, n)(gen);
cout << u << " " << v << endl;
}
return 0;
}
ac代码:(因为原题不能下载数据,所以跑过来发一篇博客)
代码直接拿自己的ac代码过来贴的,有几个板子,因为懒得改了,就这么发了。
# include <bits/stdc++.h>
using namespace std ;
namespace predefine {
const long long inf = 0x3f3f3f3f3f3f3f3f ;
using ll = long long ;
using Int = __int128 ;
using pll = pair < ll , ll > ;
# define IOS iostream::sync_with_stdio ( 0 ) ; cin.tie ( 0 ) ;
# define af( i , a , b ) for ( ll i = a ; i <= b ; ++ i )
# define df( i , a , b ) for ( ll i = a ; i >= b ; -- i )
# define Dg( x ) cout << " ------- " << x << " ------- " << '\n'
# define Dged Dg ( "Debug ed" )
# define Dgop Dg ( "Debug op" )
# define pr( x ) cout << #x << " = " << x << '\n'
# define pn putchar ('\n')
# define ps cout << "yes"
# define __fin( a ) freeopen ( a , "r" , stdin )
# define __fout( a ) freeopen ( a , "+w" , stdout )
# define lowbit( x ) ( x & ( - x ) )
// # define endl '\n'
}
using namespace predefine ;
const ll maxn = 2e5 + 10 ;
const ll mod = 1e9 + 7 ;
//----- 板子 ---------------------------------------------------------------------------------------------------------
struct SCC {
using i64 = long long ;
i64 n , cnt = 0 , tot = -1 ;
vector < vector < i64 > > mp ;
vector < i64 > d , id , stack , tag , size , val ;
vector < bool > instack ;
explicit SCC ( ll n , vector < vector < i64 > >& mp , vector < ll > &val ) :
n ( n ) , mp ( mp ) , val ( val ) , d ( vector < i64 > ( n , -1 ) ) , id ( vector < i64 > ( n ) ) ,
tag ( vector < i64 > ( n , -1 ) ) , instack ( vector < bool > ( n , 0 ) ) {}
private:
void __scc ( ll now ) {
// ps ;
d [ now ] = id [ now ] = ++ tot ;
stack.push_back ( now ) ; instack [ now ] = 1 ;
for ( auto u : mp [ now ] ) {
if ( !~d [ u ] ) {
__scc ( u ) ;
id [ now ] = min ( id [ now ] , id [ u ] ) ;
}
else if ( instack [ u ] ) {
id [ now ] = min ( id [ now ] , id [ u ] ) ;
}
}
if ( d [ now ] == id [ now ] ) {
++ cnt ;
size.push_back ( 0 ) ;
do {
size.back () += val [ stack.back () ] ;
instack [ stack.back () ] = 0 ;
tag [ stack.back () ] = cnt ;
stack.pop_back () ;
} while ( instack [ now ] ) ;
}
}
public:
void scc ( ll now ) {
-- cnt ;
__scc ( now ) ;
++ cnt ;
}
};
struct CPT {
ll n , tot = -1 , root = -1 ;
vector < vector < ll > > mp ;
vector < ll > d , id ;
vector < bool > iscp ;
explicit CPT ( ll n , vector < vector < ll > >& mp ) :
n ( n ) , mp ( mp ) , d ( vector < ll > ( n , -1 ) ) ,
id ( vector < ll > ( n , -1 ) ) , iscp ( vector < bool > ( n , 0 ) ) {} ;
private:
void __cutpoint ( ll now ) {
d [ now ] = id [ now ] = ++ tot ;
ll child = 0 ;
for ( auto u : mp [ now ] ) {
if ( !~d [ u ] ) {
__cutpoint ( u ) ;
id [ now ] = min ( id [ now ] , id [ u ] ) ;
if ( id [ u ] >= d [ now ] ) {
++ child ;
if ( now != root || child >= 2 ) {
iscp [ now ] = 1 ;
}
}
}
else id [ now ] = min ( d [ u ] , id [ now ] ) ;
}
}
public:
void cutpoint ( ll now , ll root ) {
this ->root = root ;
__cutpoint ( now ) ;
this ->root = -1 ;
}
};
struct CEG {
ll n , tot = -1 ;
vector < pll > edge ;
vector < vector < ll > > mp ;
vector < ll > d , id ;
vector < ll > ans ;
explicit CEG ( ll n ) :
n ( n ) , d ( vector < ll > ( n , -1 ) ) , id ( vector < ll > ( n , - 1 ) ) ,
mp ( vector < vector < ll > > ( n ) ) {} ;
private :
void __cutedge ( ll now , ll __edge ) {
d [ now ] = id [ now ] = ++ tot ;
for ( auto tag : mp [ now ] ) {
auto& here = edge [ tag ].second ;
if ( !~d [ here ] ) {
__cutedge ( here , tag ) ;
id [ now ] = min ( id [ now ] , id [ here ] ) ;
if ( id [ here ] > d [ now ] ) {
ans.push_back ( tag ) ;
}
}
else if ( tag != ( __edge ^ 1 ) ) {
id [ now ] = min ( id [ here ] , id [ now ] ) ;
}
}
}
public:
void add ( ll u , ll v ) {
edge.emplace_back ( u , v ) ;
mp [ u ].push_back ( (ll)edge.size () - 1 ) ;
}
void cutedge ( ll u , ll __edge ) {
__cutedge ( u , __edge ) ;
}
};
//----- 板子 ---------------------------------------------------------------------------------------------------------
Int Pow ( Int a , Int b ) {
a = a ; Int ans = 1 ;
for ( ; b ; b >>= 1 ) { if ( b & 1 ) ans = ( a * ans ) ; a = ( a * a ) ; }
return ans ; }
ll Pow ( ll a , ll b , ll mod ) {
a = a % mod ; ll ans = 1 ;
for ( ; b ; b >>= 1 ) { if ( b & 1 ) ans = ( a * ans ) % mod ; a = ( a * a ) % mod ; }
return ans ; }
inline ll sum1 ( ll _a ) { return ( _a * ( _a + 1 ) ) >> 1 ; }
inline ll sum2 ( ll _b ) { return _b * ( _b + 1 ) * ( 2 * _b + 1 ) / 6 ; }
ll dx [ 4 ] = { -1 , 0 , 1 , 0 } ;
ll dy [ 4 ] = { 0 , 1 , 0 , -1 } ;
void solve ()
{
ll n , m ;
cin >> n >> m ;
CEG g ( n ) ;
auto add = [ & ] ( ll& u , ll& v ) {
g.add ( u , v ) ;
};
// map < ll , pll > mp ;
af ( i , 0 , m - 1 ) {
ll u , v ; cin >> u >> v ;
-- u , -- v ;
// mp [ i ] = { u , v } ;
add ( u , v ) ; add ( v , u ) ;
// ps ;
}
af ( i , 0 , n - 1 ) {
if ( !~g.d [ i ] ) {
g.cutedge ( i , inf ) ;
}
}
cout << g.ans.size () << endl ;
// map < pll , ll > mp1 ;
// for ( auto u : g.ans ) {
// auto& [ x , y ] = g.edge [ u ] ;
// ++ mp1 [ { x , y } ] ;
// ++ mp1 [ { y , x } ] ;
// }
// for ( auto& [ _ , u ] : mp ) {
// if ( mp1 [ u ] ) {
// auto& [ x , y ] = u ;
// cout << x + 1 << ' ' << y + 1 << endl ;
// }
// }
}
int main () {
// IOS
// init () ;
ll _ = 1 ;
// cin >> _ ;
while ( _ -- ) {
solve () ;
}
return 0 ;
}
/*
//----- 数据 ---------------------------------------------------------------------------------------------------------
1
3 5
011
1
100
000
3
010
100
2
110
000
3
000
000
3
001
000
1
end of file
----------
*/