HDU 4612 (13年多校第二场1002)无向图缩点,有重边
这道题是多校的题,比赛的时候是一道纷纷水过的板刷题。
题意:给你一些无向边,只加一条边,使该图的桥最少,然后输出最少的桥。
思路:当时大致想到思路了,就是缩点之后找出最长的链,然后用总的桥数减去链上的桥数。
也是这么写的,但是卡在了重边上。。
还是接触的题目太少了。。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 2505 #define inf 1<<28 #define LL(x) ( x << 1 ) #define RR(x) ( x << 1 | 1 ) #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) #define PII pair<int,int> using namespace std; #define M 2000005 #define N 200005 #pragma comment(linker,"/STACK:102400000,102400000") inline void RD(int &ret) { char c; do { c = getchar(); } while(c < '0' || c > '9') ; ret = c - '0'; while((c=getchar()) >= '0' && c <= '9') ret = ret * 10 + ( c - '0' ); } struct edge{ int e , next , sign ; }ed[M] ,reed[M] ; int n , m ; int head[N] ,num ,rehead[N] ,renum ; int dfn[N] , low[N] ,st[N] ,inst[N] , belong[N] ; int dp ,top ,cnt ; int dis[N] ; bool vis[N] ; int bridgenum ; void add(int s ,int e){ ed[num].e = e ; ed[num].sign = 0 ; ed[num].next = head[s] ; head[s] = num ++ ; } void readd(int s ,int e){ reed[renum].e = e ; reed[renum].sign = 0 ; reed[renum].next = rehead[s] ; rehead[s] = renum ++ ; } void init(){ mem(dfn, 0) ; mem(low , 0) ; mem(st ,0) ; mem(belong ,0) ; mem(head, -1) ; num = 0 ; dp = 0 ; top = 0 ; cnt = 0 ; mem(rehead,-1) ; renum = 0 ; bridgenum = 0 ; } void tarjan(int now ,int fa){ dfn[now] = low[now] = ++ dp ; st[top ++ ] = now ; inst[now] = 1 ; for (int i = head[now] ; ~i ; i = ed[i].next ){ if(ed[i].sign)continue ; ed[i].sign = ed[i ^ 1].sign = 1 ; int e = ed[i].e ; if(!dfn[e]){ tarjan(e , now) ; low[now] = min(low[now] ,low[e]) ; if(dfn[now] < low[e]){ bridgenum ++ ; } } else if(inst[e]){ low[now] = min(low[now] , dfn[e]) ; } } if(low[now] == dfn[now]){ int xx ; cnt ++ ; do{ xx = st[-- top] ; inst[xx] = 0 ; belong[xx] = cnt ; }while(xx != now) ; } } void build(){ for (int i = 1 ; i <= n ; i ++ ){ dp = 0 ,top = 0 ; if(!dfn[i]){ tarjan(i ,-1) ; } } for (int i = 1 ; i <= n ; i ++ ){ for (int j = head[i] ; ~j ; j = ed[j].next ){ int e = ed[j].e ; if(belong[i] == belong[e])continue ; readd(belong[i] , belong[e]) ; readd(belong[e] ,belong[i]) ; } } } queue<int>qe ; int pos ; int bfs(int s){ while(!qe.empty())qe.pop() ; dis[s] = 0 ; mem(vis , 0) ; vis[s] = 1 ; qe.push(s) ; int ans = 0 ; while(!qe.empty()){ int temp = qe.front() ; qe.pop() ; for (int i = rehead[temp] ; ~i ; i = reed[i].next){ int e = reed[i].e ; if(!vis[e]){ dis[e] = dis[temp] + 1 ; vis[e] = 1 ; qe.push(e) ; if(ans < dis[e]){ ans = dis[e] ; pos = e ; } } } } return ans ; } int main() { while(scanf("%d%d",&n,&m) , (n + m)){ init() ; while(m -- ){ int a , b ; RD(a) ;RD(b) ; add(a , b) ; add(b , a) ; } build() ; bfs(1) ; int now = bfs(pos) ; printf("%d\n",bridgenum - now) ; } return 0 ; }