GYM 100712 H.Bridges(边双连通分量)
2017-03-13 17:13
239 查看
Description
给出一个n个点m条边的无向图,要求新加一条边使得加完边后的新图的桥最少
Input
第一行一整数T表示用例组数,每组用例首先输入两整数n和m分别表示点数和边数,之后m行每行两个整数u和v表示u和v之间有一条边(1<=T<=64,3<=n<=1e5,n-1<=m<=1e5)
Output
输出加一条边后最少的桥数
Sample Input
Sample Output
1
0
Solution
Tarjan缩点,对缩完点的树求一遍直径,连接直径的两个端点减少的桥数最多,原先的桥数减去直径长度即为答案
Code
给出一个n个点m条边的无向图,要求新加一条边使得加完边后的新图的桥最少
Input
第一行一整数T表示用例组数,每组用例首先输入两整数n和m分别表示点数和边数,之后m行每行两个整数u和v表示u和v之间有一条边(1<=T<=64,3<=n<=1e5,n-1<=m<=1e5)
Output
输出加一条边后最少的桥数
Sample Input
Sample Output
1
0
Solution
Tarjan缩点,对缩完点的树求一遍直径,连接直径的两个端点减少的桥数最多,原先的桥数减去直径长度即为答案
Code
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; #define INF 0x3f3f3f3f #define maxn 111111 #define maxm 222222 struct Edge { int to,next; bool flag;//标记是否是桥 }edge[maxm]; int head[maxn],tot; int low[maxn],dfn[maxn],stack[maxn],belong[maxn];//belong数组的值是1~block int index,top; int block;//边双连通块数 bool instack[maxn]; int bridge;//桥的数目 void addedge(int u,int v) { edge[tot].to=v,edge[tot].next=head[u],edge[tot].flag=0; head[u]=tot++; } void Tarjan(int u,int pre) { int v; low[u]=dfn[u]=++index; stack[top++]=u; instack[u]=1; for(int i=head[u];~i;i=edge[i].next) { v=edge[i].to; if(v==pre)continue; if(!dfn[v]) { Tarjan(v,u); if(low[u]>low[v])low[u]=low[v]; if(low[v]>dfn[u]) { bridge++; edge[i].flag=1; edge[i^1].flag=1; } } else if(instack[v]&&low[u]>dfn[v]) low[u]=dfn[v]; } if(low[u]==dfn[u]) { block++; do { v=stack[--top]; instack[v]=0; belong[v]=block; } while(v!=u); } } void init() { memset(dfn,0,sizeof(dfn)); memset(stack,0,sizeof(stack)); index=block=top=bridge=tot=0; memset(head,-1,sizeof(head)); } int T,n,m,e[maxn][2],deep,pos; int dfs(int u,int fa,int cnt) { if(cnt>deep)deep=cnt,pos=u; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa)continue; dfs(v,u,cnt+1); } } int main() { scanf("%d",&T); while(T--) { init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&e[i][0],&e[i][1]); addedge(e[i][0],e[i][1]),addedge(e[i][1],e[i][0]); } Tarjan(1,1); init(); int ans=0; for(int i=1;i<=m;i++) { int u=belong[e[i][0]],v=belong[e[i][1]]; if(u!=v) ans++,addedge(u,v),addedge(v,u); } deep=0; dfs(1,1,0); deep=0; dfs(pos,pos,0); printf("%d\n",ans-deep); } return 0; }
相关文章推荐
- Gym 100712H(边双联通+树的直径)
- Gym 100712H(边双联通+树的直径)
- Gym 100712E 贪心
- GYM 100712 A.Who Is The Winner?(水~)
- Gym - 100712B 预处理暴力
- 【Gym 100712B】Rock-Paper-Scissors
- GYM 100712 B.Rock-Paper-Scissors(水~)
- Gym 100712H(边双联通+树的直径)
- GYM 100712 C.Street Lamps(贪心)
- Gym 100712H(边双联通+树的直径)
- GYM 100712 E.Epic Professor(水~)
- Gym - 100712 F输出最长边的最小生成树
- Gym 100712H(边双联通+树的直径)
- GYM 100712 F.Travelling Salesman(最小生成树-Kruskal)
- Gym - 100712H Bridges(边—双连通分量)
- Gym 100712H(边双联通+树的直径)
- GYM 100712 G.Heavy Coins(枚举)
- Gym - 100712B Rock-Paper-Scissors
- Gym 100712H(边双联通+树的直径)
- Gym-100712B-Rock-Paper-Scissors