传送门:Warm up
题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目。
分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多,因此ans=树的边数-树的直径。
#pragma comment(linker,"/STACK:1024000000,1024000000") #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <cstdlib> #include <stack> #include <vector> #include <set> #include <map> #define LL long long #define mod 100000000 #define inf 0x3f3f3f3f #define eps 1e-6 #define N 200010 #define FILL(a,b) (memset(a,b,sizeof(a))) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define PII pair<int,int> using namespace std; struct edge { int v,next; edge(){} edge(int v,int next):v(v),next(next){} }e[N*10],e2[N*10]; int n,step,scc,top,tot; int head[N],dfn[N],low[N],belong[N],Stack[N]; bool instack[N],vis[N*10]; vector<int>g[N]; void init() { tot=0;top=0;scc=0; FILL(head,-1);FILL(dfn,0); FILL(low,0);FILL(instack,false); FILL(vis,false); } void addedge(int u,int v) { e[tot]=edge(v,head[u]); head[u]=tot++; } void tarjan(int u) { int v; dfn[u]=low[u]=++step; Stack[top++]=u; instack[u]=true; int pre_num=0; for(int i=head[u];~i;i=e[i].next) { v=e[i].v; if(vis[i])continue; vis[i]=vis[i^1]=true; if(!dfn[v]) { tarjan(v); if(low[u]>low[v])low[u]=low[v]; } else if(instack[v]) { if(low[u]>dfn[v])low[u]=dfn[v]; } } if(dfn[u]==low[u]) { scc++; do { v=Stack[--top]; instack[v]=false; belong[v]=scc; }while(v!=u); } } int tree_len,x; void dfs_tree(int u,int f,int d) { if(d>=tree_len)tree_len=d,x=u; for(int i=0,sz=g[u].size();i<sz;i++) { int v=g[u][i]; if(v==f)continue; dfs_tree(v,u,d+1); } } void solve() { for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i); for(int i=1;i<=n;i++)g[i].clear(); for(int u=1;u<=n;u++) { for(int i=head[u];~i;i=e[i].next) { int v=e[i].v; if(belong[u]!=belong[v]) { g[belong[u]].push_back(belong[v]); } } } tree_len=0; dfs_tree(1,-1,0); dfs_tree(x,-1,0); printf("%d\n",scc-1-tree_len); } int main() { int m,u,v; while(scanf("%d%d",&n,&m)>0) { if(n+m==0)break; init(); for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } solve(); } }
原文:http://www.cnblogs.com/lienus/p/4280064.html