纠结半天怎么用原来的模板表示边与序号的关系,map都用上了,还是一塌糊涂,然而,这是图啊……怎么能把链式前向星忘了→_→
具体看注释 ,思路当然和那些都一样
/*********** poj1515 2015.11.20 796K 157MS G++ 2230B ***********/ #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <stack> using namespace std; const int MAXN=1111; struct Edge { int v,next; bool vis; }edge[MAXN*MAXN]; int n,m,NE; int head[MAXN]; void Insert(int u,int v) { edge[NE].v=v; edge[NE].next=head[u]; edge[NE].vis=false; head[u]=NE++; } int cnt,_count; int low[MAXN],dfn[MAXN],color[MAXN]; bool mark[MAXN]; stack<int>S; void Tarjan(int u,int father) { int flag=0; low[u]=dfn[u]=++cnt; mark[u]=true; S.push(u); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==father&&!flag) { flag=1; continue; } if(dfn[v]==0) { Tarjan(v,u); low[u]=min(low[u],low[v]); } else if(mark[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { int v; _count++; do{ v=S.top(); S.pop(); mark[v]=false; color[v]=_count;//标记每个点所在的集合序号 }while(u!=v); } } void Solve(int u,int father) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==father) continue; if(color[u]==color[v]&&!edge[i].vis) printf("%d %d\n",u,v);//因为在同一个连通分量中 双向的边输出一个方向的就好 else if(color[u]!=color[v]&&!edge[i].vis) { printf("%d %d\n",u,v); printf("%d %d\n",v,u);//因为是桥 所以输出双向的 } edge[i].vis=true; edge[i^1].vis=true;//不管是输出了单向的还是双向的 这条边都结束了 if(!mark[v]) { mark[v]=true; Solve(v,u); } } } int main() { // freopen("cin.txt","r",stdin); int u,v,t=1; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; NE=0; memset(head,-1,sizeof(head)); while(m--) { scanf("%d%d",&u,&v); Insert(u,v); Insert(v,u); } cnt=_count=0; memset(dfn,0,sizeof(dfn)); memset(mark,false,sizeof(mark)); Tarjan(1,-1); printf("%d\n\n",t++); memset(mark,false,sizeof(mark)); mark[1]=true; Solve(1,-1); puts("#"); } return 0; }