标签:另一个 scanf str else ons tarjan scan print one
题意:
有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走。现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指:没有公共边的路,但可以经过同一个中间顶点。
该图中为连通图
题解:
题意转换一下:
就是给了一个连通图,问加多少条边可以变成边双连通。
我们将原图先缩点, 可以得到一棵树.然后我们统计叶子节点数目leaf(即度为1的点), 最小的加边数即(leaf+1)/2 (成对加边)
考虑重边
代码:
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include<vector> #include <map> using namespace std; const int maxn = 5010;//点数 const int maxm = 20010;//边数,因为是无向图,所以这个值要*2 struct Edge { int to,next; bool cut;//是否是桥标记 } edge[maxm]; int head[maxn],tot; int low[maxn],dfn[maxn],Stack[maxn],belong[maxn];//belong数组的值是1~scc int Index,top; int scc;//边双连通块数/强连通分量的个数 bool Instack[maxn]; int bridge;//桥的数目 int cut[maxn]; void addedge(int u,int v) { edge[tot].to = v; edge[tot].next = head[u]; edge[tot].cut=false; head[u] = tot++; } void Tarjan(int u,int pre) { int v; low[u] = dfn[u] = ++Index; Stack[top++] = u; Instack[u] = true; int son=0; for(int i = head[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(v == pre)continue; if( !dfn[v] ) { son++; Tarjan(v,u); if( low[u] > low[v] )low[u] = low[v]; if(low[v] > dfn[u]) { bridge++; edge[i].cut = true; edge[i^1].cut = true; } if(u == pre && son > 1)cut[u] = true; if(u != pre && low[v] >= dfn[u])cut[u] = true; } else if( Instack[v] && low[u] > dfn[v] ) low[u] = dfn[v]; } if(low[u] == dfn[u]) { scc++; do { v = Stack[--top]; Instack[v] = false; belong[v] = scc; } while( v!=u ); } } void init() { tot = 0; memset(head,-1,sizeof(head)); } int du[maxn]; void solve(int n) { memset(dfn,0,sizeof(dfn)); memset(Instack,false,sizeof(Instack)); memset(du,0,sizeof du); memset(cut,0,sizeof cut); Index = top = scc = 0; bridge = 0; for(int i = 1; i <= n; i++) if(!dfn[i]) Tarjan(i,i); for(int i = 1; i <= n; i++) for(int j = head[i]; j != -1; j = edge[j].next) if(edge[j].cut) du[belong[i]]++; int ans=0; for(int i = 1; i <= scc; i++) if(du[i]==1) ans++; //找叶子结点的个数ans,构造边双连通图需要加边(ans+1)/2 printf("%d\n",(ans+1)/2); } int main() { int n,m; int u,v; while(scanf("%d%d",&n,&m)==2) { init(); while(m--) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } solve(n); } return 0; }
标签:另一个 scanf str else ons tarjan scan print one
原文地址:https://www.cnblogs.com/j666/p/11630735.html