原题链接:点击打开链接
题目大意为:
给你一个n (n<=200 000)点,m (m<=1000 000)条边的无向图(无向图含重边)。
询问在图中添加一条边后,能够使得新图中的桥最少。
在无向图中的任意一条路径上,如果路径中含有桥,我们只要连接路径的两个端点,就可以将路径中的桥取缔。
因此,题目变为在图中找一条含有桥的数量最多的路径。
算法设计:
利用塔尖算法标记出无向图中的所有桥。
把图中所有的桥设置权值为1,非桥的边权值为0。
此时,在途中给找出一条权值最大的路径。
看网上的题解,说可以建立一颗包涵所有桥的树,然后求树的直径。但我的方法并没有建立树,而是直接在原有的图像图中,利用Heap+Bfs(类似于Heap+Dijkstra)找出的最长链。
而在题目中,由于数据比较大,会发生栈溢出,因此要添加语句:
#pragma comment(linker,"/STACK:102400000,1024000")
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<map> #include<algorithm> #include<map> #include<stack> #pragma comment(linker,"/STACK:102400000,1024000") using namespace std; const int inf=999999999; const int maxn=200005; struct Edge{ int from, to; int dist; Edge (){}; Edge (int a,int b):from(a),to(b),dist(0){} }; vector<Edge>edges; vector<int>G[maxn]; int cnt_bridge; void add(int a,int b){ Edge e(a,b); edges.push_back(e); e.from=b;e.to=a; edges.push_back(e); int mm=edges.size(); G[a].push_back(mm-2); G[b].push_back(mm-1); } int pre[maxn]; bool iscut[maxn]; int dfs_clock; int low[maxn]; class Cuts_Bridges{ public: int n; void init(int n){ this->n=n; for(int i=1;i<=n;i++)G[i].clear(); edges.clear(); memset(iscut,0,sizeof(iscut)); memset(pre,0,sizeof(pre)); dfs_clock=0; cnt_bridge=0; } int dfs(int u,int fa,int lastEdge){ int lowu=pre[u]=++dfs_clock; int child=0; for(int i=0;i<G[u].size();i++){ Edge &e=edges[G[u][i]]; int v=e.to; if(!pre[v]){ child++; int lowv=dfs(v,u,G[u][i]); lowu=min(lowv,lowu); if(lowv>=pre[u]){ iscut[u]=true; if(lowv>pre[u]){ e.dist=edges[G[u][i]^1].dist=1; cnt_bridge++; } } } else if(pre[v]<pre[u]&&lastEdge!=(G[u][i]^1)) lowu=min(lowu,pre[v]); } if(fa<0&&child==1)iscut[u]=0; low[u]=lowu; return lowu; } }Do; bool done[maxn]; int d[maxn]; struct HeapNode{ int d,u; bool operator<(const HeapNode& rhs)const { return d<rhs.d; } }; void Dijkstra(int s,int n){ priority_queue<HeapNode>Q; for(int i=0;i<=n;i++)d[i]=-inf; d[s]=0; memset(done,0,sizeof(done)); HeapNode inp; inp.d=0; inp.u=s; Q.push(inp); while(!Q.empty()){ HeapNode x=Q.top(); Q.pop(); int u=x.u; if(done[u])continue; done[u]=true; for(int i=0;i<G[u].size();i++){ Edge &e=edges[G[u][i]]; if(done[e.to])continue; if(d[e.to]<d[u]+e.dist){ d[e.to]=d[u]+e.dist; inp.d=d[e.to]; inp.u=e.to; Q.push(inp); } } } } int solve(int n){ Dijkstra(1,n); int max=-inf,p=1; for(int i=1;i<=n;i++){ if(d[i]>max){ max=d[i];p=i; } } Dijkstra(p,n); max=-inf,p=1; for(int i=1;i<=n;i++)if(d[i]>max){ max=d[i];p=i; } return max; } int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){ Do.init(n); int a,b; for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); add(a,b); } Do.dfs(1,-1,-1); int tmp=solve(n); printf("%d\n",cnt_bridge-tmp); } return 0; } /** 8 10 1 2 1 3 2 3 3 4 5 8 4 5 4 6 4 3 5 6 6 7 ans:0 8 9 1 2 1 3 2 3 3 4 5 8 4 5 4 6 5 6 6 7 ans:1 4 4 1 2 1 3 1 4 2 3 ans:0 **/