HDU4612-强连通分量&树的直径-warmup
来源:互联网 发布:java获取 路径 编辑:程序博客网 时间:2024/05/21 07:04
给定一个图,要求你添加一个边,使这个图的桥最少。
我几乎是蒙蔽的。
先缩个点,然后求一遍树的直径。
然后用 原先的桥数 减去树的直径就好了。
或者 用强连通分量树 -1-树的直径
(缩点后一个scc就是一个点,而桥就是边,并且是树,如果不是树就缩点缩了)
发现了吧。有的人把剩下的桥 叫做 枝叶边, 就是那个红点那个边
就是要求的 剩下的最小的桥数
(要求添加的那个一边,从直径头到尾,把所有直径边想当桥的愿望都给否定了)
#include <iostream>#include <cstdio>#include <cstring>#include <bits/stdc++.h>/*先缩点,变成一个树,然后再求树的直径,然后那个原来的桥数减去直径 在减1(因为还要在添)*/using namespace std;const int maxm=1000008;const int maxn=200005;struct Node{ int to,next,cost;}node[maxm*2];int len;int head[maxn];void add(int u,int v){ node[len].to=v; node[len].next=head[u]; //node[len].cost=w; head[u]=len++;}int low[maxn];int dfn[maxn];int cnt[maxn];int num[maxn];int index;int bridge;int scc;vector<int>G[maxn];stack<int>s;int m,n,a,b;void init(){ index=0; len=0; scc=0; bridge=0; memset(head,-1,sizeof(head));//链表 memset(num,0,sizeof(num));//各scc多少个 memset(dfn,0,sizeof(dfn));// memset(low,0,sizeof(low)); for(int i=0;i<maxn;i++) G[i].clear(); while(!s.empty()) s.pop();}void tarjan(int m,int pre){ low[m]=dfn[m]=++index; s.push(m); for(int i=head[m];i!=-1;i=node[i].next) { if(i==(pre^1))continue; int v=node[i].to; if(!dfn[v]) { tarjan(v,i); if(low[v]<low[m]) low[m]=low[v]; if(low[v]>dfn[m])//这就是 桥的条件 bridge++; }else if(dfn[v]<low[m])//下一个点的dfs顺序比他能到达的小,就换 low[m]=dfn[v]; } if(low[m]==dfn[m]) { scc++; for(;;) { int x = s.top();s.pop(); cnt[x]=scc; num[scc]++; if(x==m)break; } }}int dis[maxn];bool vis[maxn];int dfs(int a){ for(int i=0;i<G[a].size();i++){ int v=G[a][i]; if(!vis[v]) {vis[v]=true; dis[v]=dis[a]+1; dfs(v); } }}void solve(){ memset(dis,0,sizeof(dis)); memset(vis,false,sizeof(vis)); vis[1]=true; dis[1]=0; dfs(1); int dex=1; int sum=-1; for(int i=1;i<=scc;i++){ if(dis[i]>sum) {sum=dis[i];// dex=i; } } memset(dis,0,sizeof(dis)); memset(vis,false,sizeof(vis)); vis[dex]=true; dis[dex]=0; dfs(dex); sum=-1; dex=1; for(int i=1;i<=scc;i++){ if(dis[i]>sum) sum=dis[i]; } // cout<<bridge<<endl; //cout<<sum<<endl;//printf("%d\n",bridge-sum);printf("%d\n",scc-1-sum);}int main(){ while(~scanf("%d%d",&m,&n)){ if(m==0||n==0) break; init(); for(int i=1;i<=n;i++){ scanf("%d%d",&a,&b); add(a,b); add(b,a); } for(int i=1;i<=m;i++) if(!dfn[i]) tarjan(i,-1); for(int i=1;i<=m;i++){ for(int j=head[i];j!=-1;j=node[j].next) { int v=node[j].to; if(cnt[v]==cnt[i]) continue; G[cnt[v]].push_back(cnt[i]); G[cnt[i]].push_back(cnt[v]);//缩点 } } solve(); } return 0;}
阅读全文
0 0
- HDU4612-强连通分量&树的直径-warmup
- HDU4612 Warm up(强联通分量+缩点重构图后求树的直径)
- hdu4612 Warm up 树形dp 桥 强连通分量
- hdu4612(缩点+树的直径)
- hdu 4612 求边连通分量+求树的直径
- HDU4612-Warm up(无向图强连通分量缩点)
- 图的强连通分量
- hdu4612(双联通缩点+求树的直径)
- 有向图的强连通分量
- 有向图的强连通分量
- 有向图的强连通分量
- 有向图的强连通分量
- 有向图的强连通分量
- 求图的强连通分量
- 强连通分量的三种算法
- 有向图的强连通分量
- 强连通分量的三种算法
- 强连通分量缩点的模板
- JAVA线程池shutdown和shutdownNow的区别
- Linux \windows的Nginx静态代理配置文件
- iMindMap的起点,你选对了吗?
- ExecutorService线程池的使用
- mybatis xml文件中的大于、小于、及like模糊查询的写法
- HDU4612-强连通分量&树的直径-warmup
- 利用属性动画实现一个不一样的SplashView
- linux学习 变量类型
- Eclipse 积累
- Android修改图片的大小
- Android API:Activity.managedQuery()
- 为IOStream平反
- hssfworkbook写大量数据数据慢
- Sliding Window POJ