acdream 1236 Burning Bridges tarjan

傳送門:acdream 1236

        n個節點由m條邊相連,現在要毀掉一些邊,但要保證整張圖還是連通的,問哪些邊絕對不會被毀掉


       這就是一個圖論找橋的問題

       利用tarjan算法對於邊(u,v)如果該邊是v的父親邊,且dfn[v]==low[v]則該邊是橋

/******************************************************
 * File Name:   b.cpp
 * Author:      kojimai
 * Creater Time:2014年10月07日 星期二 12時08分22秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define FFF 10005
int first[FFF],e,dfn[FFF],low[FFF],cnt;
#define FF 100005
struct node
{
	int u,v,next;
}edge[FF*2];
vector<int> ans;
void addedge(int x,int y)
{
	edge[e].u = x;edge[e].v = y;edge[e].next = first[x];first[x] = e++;
	edge[e].v = x;edge[e].u = y;edge[e].next = first[y];first[y] = e++;
}
int pre[FFF];
void tarjan(int x)
{
	dfn[x] = low[x] = cnt++;
	for(int k = first[x];~k;k = edge[k].next)
	{
		int v = edge[k].v;
		if(dfn[v] == -1) {
			pre[v] = k;
			tarjan(v);
			low[x] = min(low[x],low[v]);
		}
		else if(pre[x]/2 != k/2)
			low[x] = min(low[x],dfn[v]);
	}
	if(pre[x]!=-1 &&low[x] == dfn[x])
		ans.push_back(pre[x]/2+1);
}
int main()
{
	int n,m,x,y;
	memset(first,-1,sizeof(first));
	e = 0;
	scanf("%d%d",&n,&m);
	for(int i = 0;i < m;i++)
	{
		scanf("%d%d",&x,&y);
		addedge(x,y);
	}
	memset(dfn,-1,sizeof(dfn));
	memset(low,0,sizeof(low));
	cnt = 1;
	pre[1] = -1;
	tarjan(1);
	//for(int i = 1;i<=n;i++)
	//	cout<<"dfn="<<dfn[i]<<" low="<<low[i]<<endl;
	cout<<ans.size()<<endl;
	for(int i = 0;i < ans.size();i++)
	{
		cout<<ans[i];
		if(i<ans.size()-1)
			cout<<' ';
		else
			cout<<endl;
	}
	return 0;
}


發佈了109 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章