<题目链接>
题目大意:
给定一个无向图,让你尽可能的删边,但是删边之后,仍然需要保证图的连通性,输出那些不能被删除的边。
解题分析:
就是无向图求桥的题目,主要是提高一下处理重边的姿势。
#include <bits/stdc++.h> using namespace std; #define pb push_back #define clr(a,b) memset(a,b,sizeof(a)) #define rep(i,s,t) for(int i=s;i<=t;i++) const int N = 1e4+5 , M = 1e5+5; struct Edge{ int from,to,id,fp,nxt; }e[M<<1]; int n,m,tot,cnt; int head[N],dfn[N],low[N],cut[M]; vector<int>vec; inline void init(){ cnt=tot=0; vec.clear(); clr(dfn,0);clr(head,-1);clr(cut,0); } inline void add(int u,int v,int id){ e[cnt]=(Edge){u,v,id,0,head[u]};head[u]=cnt++; } inline bool isHash(int u,int v){ //因为添加的是双向边,所以这里直接判断一个方向是否有相同边即可 for(int i=head[u];~i;i=e[i].nxt){ int vv=e[i].to; if(vv==v){ e[i].fp=1; return false; } }return true; } void Tarjan(int u,int pre){ dfn[u]=low[u]=++tot; for(int i=head[u];~i;i=e[i].nxt){ int v=e[i].to; if(v==pre)continue; if(!dfn[v]){ Tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>dfn[u]&&!e[i].fp){ vec.pb(e[i].id); //存下符合条件的割边 } }else low[u]=min(low[u],dfn[v]); } } inline void Solve(){ printf("%d ",vec.size()); sort(vec.begin(),vec.end()); for(int i=0;i<vec.size();i++){ if(i!=0)printf(" "); printf("%d",vec[i]); } if(vec.size())puts(""); } int main(){ int T;cin>>T; while(T--){ read(n);read(m); init(); rep(i,1,m){ int u,v;scanf("%d%d",&u,&v); if(isHash(u,v)){ //判断重边 add(u,v,i);add(v,u,i); } } Tarjan(1,-1); Solve(); if(T)puts(""); } }