Warm up HDU - 4612 无向图缩点+树的直径
2017-10-08 15:47
344 查看
题意:n个点,m条无向边。如果去掉一条边,使图不连通,那么这条边就称之为桥。可以加一条边,使图中的桥最少,这个时候桥为多少?
题解:先缩点,缩完之后是一棵树,树的边都是桥。然后求树的直径,将直径相连是最优的。ans=树的边数-直径的长度。
分析:
之前只写过有向图的缩点。这个缩点和有向图差不多,加一个标记就行了。注意这里还要将桥都记下来,然后重新建图。
例子:
6 8
1 2
2 3
3 4
4 5
2 6
6 2
1 3
4 7
有环,不会扫完所有点。
那个异或的用法,强…
题解:先缩点,缩完之后是一棵树,树的边都是桥。然后求树的直径,将直径相连是最优的。ans=树的边数-直径的长度。
分析:
之前只写过有向图的缩点。这个缩点和有向图差不多,加一个标记就行了。注意这里还要将桥都记下来,然后重新建图。
例子:
6 8
1 2
2 3
3 4
4 5
2 6
6 2
1 3
4 7
有环,不会扫完所有点。
那个异或的用法,强…
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <set> #include <map> using namespace std; #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) const int maxn = 200010; const int maxm = 1000010; int sd[maxn],rd[maxn],cd[maxn],dian[maxn],head[maxn],low[maxn],dfn[maxn],st[maxn],vis_st[maxn]; int bb[maxm][2],d[maxn],vis[maxn],top=0,tot=0,num=0,numb=0; struct node{ int to,pre,flag; }e[maxm*2]; void ini() { mem(st,0);mem(bb,0);mem(d,0);mem(vis,0);mem(dfn,0);mem(low,0);mem(vis_st,0);mem(e,0);mem(sd,0);mem(rd,0);mem(cd,0);mem(dian,0);mem(head,-1); top=0,tot=0,num=0,numb=0; } void addedge(int h,int a,int b) { e[h].to=b;e[h].pre=head[a];e[h].flag=1;head[a]=h; } void Tarjan(int u) { st[++top]=u; dfn[u]=low[u]=++tot; vis_st[u]=1; for(int i=head[u];i>-1;i=e[i].pre) { node t=e[i]; if(!e[i].flag) continue; e[i].flag=e[i^1].flag=0; if(!dfn[t.to]) { Tarjan(t.to); low[u]=min(low[u],low[t.to]); if(dfn[u]<low[t.to]) { bb[numb][0]=u;bb[numb++][1]=t.to; } } else {if(vis_st[t.to]) low[u]=min(low[u],low[t.to]);} } if(dfn[u]==low[u]) { sd[num++]=u; int a; do{ a=st[top--]; vis_st[a]=0; dian[a]=u; }while(u!=a); } } void dfs(int u,int h) { vis[u]=1; for(int i=head[u];i>-1;i=e[i].pre) { int t=dian[e[i].to]; if(!vis[t]) dfs(t,h+1); } d[u]=h; } int main() { int N,M,maxx=0,k=0; while(scanf("%d %d",&N,&M)!=EOF&&N+M) { ini();int h=0; num=top=tot=0,maxx=0,k=0;; for(int i=0;i<M;i++) { int a,b; scanf("%d %d",&a,&b); addedge(h,a,b);h++; addedge(h,b,a);h++; } for(int i=1;i<=N;i++) if(!dfn[i]) Tarjan(i); mem(e,0);h=0;mem(vis,0);mem(d,0);mem(head,-1); for(int i=0;i<numb;i++){ addedge(h,dian[bb[i][0]],dian[bb[i][1]]);h++; addedge(h,dian[bb[i][1]],dian[bb[i][0]]);h++; } dfs(dian[1],0);k=dian[1]; for(int i=0;i<num;i++) if(maxx<d[sd[i]]) {maxx=d[sd[i]];k=sd[i];} mem(vis,0);mem(d,0); dfs(k,0);maxx=0; for(int i=0;i<num;i++) if(maxx<d[sd[i]]) maxx=d[sd[i]]; printf("%d\n",num-maxx-1); } return 0; }
相关文章推荐
- Warm up HDU - 4612 无向图缩点+树的直径
- Warm up HDU - 4612 无向图缩点+树的直径
- Warm up HDU - 4612 无向图缩点+树的直径
- Warm up HDU - 4612 无向图缩点+树的直径
- Warm up HDU - 4612 无向图缩点+树的直径
- Warm up HDU - 4612 无向图缩点+树的直径
- Warm up HDU - 4612 无向图缩点+树的直径
- Warm up HDU - 4612 无向图缩点+树的直径
- Hdu 4612 Warm up (双连通缩点+树的直径)
- HDU 4612 Warm up (边双联通,树的直径)
- hdu 4612 Warm up (带有重边的无向图Tarjan+树的直径)
- HDU 4612 Warm up(边双联通+直径【手动扩栈】)
- HDU 4612 Warm up(边双联通求树的直径)
- hdu 4612 Warm up(双连通缩点+树直径,4级)
- hdu 4612 Warm up(边-双连通+缩点+树的直径)
- HDU 4612 Warm up (树的直径 + 双联通)
- HDU 4612 Warm up(边双连通分量+树的直径)
- HDU 4612 Warm up(边双连通、树的直径)
- HDU 4612——Warm up——————【边双连通分量、树的直径】
- [kuangbin带你飞]专题九 连通图 F - Warm up HDU - 4612 缩点+树的直径