题意:
与 http://blog.csdn.net/houserabbit/article/details/38958891 类似 只不是将原本的无向图变为混合图
思路:
在上一篇我也写过了 http://blog.csdn.net/houserabbit/article/details/38958891 首先是找桥 那么就需要先把混合图变成无向图 因为题目说答案存在 因此桥必然是混合图里的无向边
然后就是块内的工作了 也是分两种边讨论 只不过判定边是否留下的时候要看一下它是不是原图的无向边 因为有向边是不能动的 最后稍微改一下输出 基本与上一篇一致
因此我们可以总结出一种思路 对于基于删边的构造强连通图的方法——找桥+块内dfs分2种边讨论 以前也曾经做过基于加边的构造强连通图 大致方法就是——强连通缩点+入度出度讨论
代码:
#include<cstdio> #include<iostream> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<set> #include<vector> using namespace std; typedef long long LL; #define N 2010 #define M 4000010 #define inf 2147483647 int n,m,t=1,tot,idx; int head[N],dfn[N],low[N]; struct edge { int u,v,next; bool vis,cut,left,dir,exit; }ed[M]; void add(int u,int v,bool dir,bool exit) { ed[tot].u=u; ed[tot].v=v; ed[tot].next=head[u]; ed[tot].vis=ed[tot].cut=ed[tot].left=false; ed[tot].dir=dir; ed[tot].exit=exit; head[u]=tot++; } void tarjan(int u) { int i,v; dfn[u]=low[u]=++idx; for(i=head[u];~i;i=ed[i].next) { v=ed[i].v; if(ed[i].vis) continue; ed[i].vis=ed[i^1].vis=true; if(dfn[v]==-1) { tarjan(v); low[u]=min(low[u],low[v]); if(dfn[u]<low[v]) { ed[i].cut=ed[i^1].cut=true; ed[i].left=ed[i^1].left=true; } } else low[u]=min(low[u],dfn[v]); } } void dfs(int u) { int i,v; dfn[u]=low[u]=++idx; for(i=head[u];~i;i=ed[i].next) { if(ed[i].cut||!ed[i].exit) continue; v=ed[i].v; if(dfn[v]==-1) { ed[i].vis=ed[i^1].vis=true; dfs(v); low[u]=min(low[u],low[v]); if(!ed[i].dir) { if(low[v]>dfn[u]) ed[i^1].left=true; else ed[i].left=true; } } else { low[u]=min(low[u],dfn[v]); if(!ed[i].vis&&!ed[i].dir) ed[i].left=true; ed[i].vis=ed[i^1].vis=true; } } } void solve() { int i; memset(dfn,-1,sizeof(dfn)); idx=0; tarjan(1); memset(dfn,-1,sizeof(dfn)); idx=0; for(i=0;i<tot;i++) ed[i].vis=false; for(i=1;i<=n;i++) { if(dfn[i]==-1) dfs(i); } } int main() { int i,u,v,k; while(~scanf("%d%d",&n,&m)) { tot=0; memset(head,-1,sizeof(head)); for(i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&k); if(k&1) { add(u,v,true,true); add(v,u,true,false); } else { add(u,v,false,true); add(v,u,false,true); } } solve(); for(i=0;i<tot;i+=2) { if(ed[i].dir) continue; if(ed[i].left&&ed[i^1].left) printf("%d %d 2\n",ed[i].u,ed[i].v); else if(ed[i].left) printf("%d %d 1\n",ed[i].u,ed[i].v); else printf("%d %d 1\n",ed[i].v,ed[i].u); } } return 0; }
时间: 2024-11-07 23:59:29