PKU 3177 Redundant Paths

無向グラフが与えられて辺を追加して、各点間に二通りの経路ができるようにする時(その経路は同じ辺を使わってはいけない) 追加する辺の個数を最小化


二重連結であれば2通り経路があるのでlowlinkを用いて適当に現在のグラフの二重連結成分を頂点にしたグラフを考えた時の(葉の個数+1)/2が答え

入力に同じ辺が2回含まれてるケースがあったらしく訴訟

//include
//------------------------------------------
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <queue>
#include <climits>
using namespace std;

//conversion
//------------------------------------------
inline int toInt(string s) {int v; istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x) {ostringstream sout;sout<<x;return sout.str();}

//math
//-------------------------------------------
template<class T> inline T sqr(T x) {return x*x;}

//typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> P;
typedef long long ll;

//container util
//------------------------------------------
#define ALL(a)  (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define pb push_back
#define mp make_pair
#define SZ(a) int((a).size())
#define EACH(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())
#define fi first
#define se second

//repetition
//------------------------------------------
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n)  FOR(i,0,n)
#define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)

//constant
//--------------------------------------------
const double EPS = 1e-10;
const double PI  = acos(-1.0);
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,1,-1};

//clear memory
#define CLR(a) memset((a), 0 ,sizeof(a))

//debug
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;

int f, r, ret;
vector<int> g[5010];
int now;
int low[5010], ord[5010];
bool vis[5010];
P e[10010];
int deg[5010];
bool use[5010][5010];

void dfs(int v){
    vis[v] = true;
    ord[v] = low[v] = now++;

    rep(i, g[v].size()){
	if(!vis[g[v][i]]){
	    use[v][g[v][i]] = true;
	    dfs(g[v][i]);
	    low[v] = min(low[v], low[g[v][i]]);
	}
	else if(!use[g[v][i]][v]) low[v] = min(low[v], ord[g[v][i]]);
    }
}

int main(){
    scanf("%d %d", &f, &r);
    rep(i, r){
	int a, b;
	scanf("%d %d", &a, &b);
	--a; --b;
	if(use[a][b]) continue;
	use[a][b] = use[b][a] = true;
	g[a].pb(b);
	g[b].pb(a);
	e[i] = mp(a, b);
    }
    memset(use, 0, sizeof(use));
    dfs(0);
    rep(i, r){
	if(low[e[i].fi] != low[e[i].se]){
	    deg[low[e[i].fi]]++;
	    deg[low[e[i].se]]++;
	}
    }
    rep(i, f) ret += (deg[i] == 1);
    //rep(i, f) printf("%d %d\n", low[i], ord[i]);
    printf("%d\n", (ret + 1) / 2);
    return 0;
}